Last active
June 5, 2018 17:46
-
-
Save Tornhoof/d4c4f27ab9319ca71037114603117837 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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