Skip to content

Instantly share code, notes, and snippets.

@Tornhoof
Last active June 5, 2018 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tornhoof/d4c4f27ab9319ca71037114603117837 to your computer and use it in GitHub Desktop.
Save Tornhoof/d4c4f27ab9319ca71037114603117837 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace HttpClientFactoryFixture
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddApplicationPart(Assembly.GetExecutingAssembly()).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc();
}
}
[Route("api/Test")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Hello World");
}
}
public class TestFixture : IAsyncLifetime
{
private readonly IWebHost _host;
public readonly HttpClient Client = new HttpClient(); // Typed HttpClient Factory would be nice here
public TestFixture()
{
var freePort = RandomPortHelper.FindFreePort();
BaseUri = $"http://localhost:{freePort}";
var builder = WebHost.CreateDefaultBuilder().UseStartup<Startup>().UseUrls(BaseUri);
_host = builder.Build();
}
public string BaseUri { get; }
public Task InitializeAsync()
{
return _host.StartAsync();
}
public async Task DisposeAsync()
{
await _host.StopAsync().ConfigureAwait(false);
Client?.Dispose();
}
}
public static class RandomPortHelper
{
private static readonly object Lock = new object();
private static readonly Random Random = new Random();
public static int FindFreePort()
{
lock (Lock)
{
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
var usedPorts = new HashSet<int>(tcpConnInfoArray.Select(t => t.LocalEndPoint.Port));
int freePort;
var counter = 0;
while (usedPorts.Contains(freePort = GetRandomNumber(1025, 65535)))
{
counter++;
if (counter > 1000)
{
throw new InvalidOperationException("Can't find port.");
}
}
return freePort;
}
}
private static int GetRandomNumber(int minValue, int maxValue)
{
lock (Lock)
{
return Random.Next(minValue, maxValue);
}
}
}
public class Tests : IClassFixture<TestFixture>
{
private readonly TestFixture _fixture;
public Tests(TestFixture fixture)
{
_fixture = fixture;
}
[Fact]
public async Task Test()
{
var uri = new UriBuilder(_fixture.BaseUri) {Path = "api/Test"}.Uri;
var result = await _fixture.Client.GetAsync(uri).ConfigureAwait(false);
Assert.True(result.IsSuccessStatusCode);
Assert.Equal("Hello World", await result.Content.ReadAsStringAsync().ConfigureAwait(false));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment