Skip to content

Commit 0380045

Browse files
authored
Replace IHttpClientFactory mock with normal dependency injection.
This way the code look closer how it is used in real world scenario's. For unittests the serviceProvider is easily created and configured, for integration tests the TestServer works the same way.
1 parent 53db122 commit 0380045

File tree

2 files changed

+81
-28
lines changed

2 files changed

+81
-28
lines changed

test/TestableHttpClient.IntegrationTests/TestableHttpClient.IntegrationTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
</ItemGroup>
1010

1111
<ItemGroup>
12+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.4" />
1213
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.4" />
1314
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
1415
<PrivateAssets>all</PrivateAssets>
1516
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1617
</PackageReference>
1718
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
18-
<PackageReference Include="Moq" Version="4.14.1" />
1919
<PackageReference Include="xunit" Version="2.4.1" />
2020
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
2121
<PrivateAssets>all</PrivateAssets>

test/TestableHttpClient.IntegrationTests/UsingIHttpClientFactory.cs

Lines changed: 80 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
using System.Net.Http;
33
using System.Threading.Tasks;
44

5-
using Moq;
5+
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.AspNetCore.TestHost;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Hosting;
11+
12+
using NFluent;
13+
14+
using TestableHttpClient.NFluent;
615

716
using Xunit;
817

@@ -17,58 +26,102 @@ public async Task ConfigureIHttpClientFactoryToUseTestableHttpClient()
1726
var testableHttpMessageHandler = new TestableHttpMessageHandler();
1827
testableHttpMessageHandler.RespondWith(response => response.WithHttpStatusCode(HttpStatusCode.OK));
1928

20-
// Create a mock for IHttpClientFactory
21-
var httpClientFactoryMock = new Mock<IHttpClientFactory>();
22-
// Setup the CreateClient method to use the testableHttpMessageHandler
23-
httpClientFactoryMock.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(new HttpClient(testableHttpMessageHandler));
29+
var services = new ServiceCollection();
30+
// Register an HttpClient and configure the TestableHttpMessageHandler as the PrimaryHttpMessageHandler
31+
services.AddHttpClient(string.Empty).ConfigurePrimaryHttpMessageHandler(() => testableHttpMessageHandler);
2432

25-
// Pass the mocked IHttpClientFactory to the class under test.
26-
var client = new HttpbinClient(httpClientFactoryMock.Object);
27-
var result = await client.Get();
33+
var serviceProvider = services.BuildServiceProvider();
2834

29-
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
35+
// Request the IHttpClientFactory
36+
var httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>();
37+
// Create the HttpClient
38+
var client = httpClientFactory.CreateClient();
39+
// And use it...
40+
_ = await client.GetAsync("https://httpbin.com/get");
41+
42+
// Now use the assertions to make sure the request was actually made.
3043
testableHttpMessageHandler.ShouldHaveMadeRequestsTo("https://httpbin.com/get");
3144
}
3245

3346
[Fact]
34-
public async Task ConfigureMultiplehttpClientFactories()
47+
public async Task ConfigureMultipleHttpMessageHandlers()
3548
{
49+
// Create multiple TestableHttpMessageHandlers as usual, if the response is not important, a single TestableHttpMessageHandler can be used.
3650
var testableGithubHandler = new TestableHttpMessageHandler();
3751
testableGithubHandler.RespondWith(response => response.WithHttpStatusCode(HttpStatusCode.OK).WithResponseHeader("Server", "github"));
3852

3953
var testableHttpBinHandler = new TestableHttpMessageHandler();
4054
testableHttpBinHandler.RespondWith(response => response.WithHttpStatusCode(HttpStatusCode.NotFound).WithResponseHeader("Server", "httpbin"));
4155

42-
// Create a mock for IHttpClientFactory
43-
var httpClientFactoryMock = new Mock<IHttpClientFactory>();
44-
// Setup the CreateClient method to use the testableHttpMessageHandler
45-
httpClientFactoryMock.Setup(x => x.CreateClient("github")).Returns(new HttpClient(testableGithubHandler));
46-
httpClientFactoryMock.Setup(x => x.CreateClient("httpbin")).Returns(new HttpClient(testableHttpBinHandler));
56+
var services = new ServiceCollection();
57+
// Register named HttpClients and configure the correct TestableHttpMessageHandler as the PrimaryHttpMessageHandler
58+
services.AddHttpClient("github").ConfigurePrimaryHttpMessageHandler(() => testableGithubHandler);
59+
services.AddHttpClient("httpbin").ConfigurePrimaryHttpMessageHandler(() => testableHttpBinHandler);
60+
var serviceProvider = services.BuildServiceProvider();
4761

48-
var httpClientFactory = httpClientFactoryMock.Object;
62+
// Request the IHttpClientFactory
63+
var httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>();
4964

65+
// Create the named HttpClient
5066
var githubClient = httpClientFactory.CreateClient("github");
51-
await githubClient.GetAsync("https://github.com/api/users");
67+
// And use it.
68+
var result = await githubClient.GetAsync("https://github.com/api/users");
69+
Check.That(result).HasResponseHeader("Server", "github").And.HasHttpStatusCode(HttpStatusCode.OK);
5270

71+
// Create another named HttpClient
5372
var httpbinClient = httpClientFactory.CreateClient("httpbin");
54-
await httpbinClient.GetAsync("https://httpbin.com/get");
73+
// And use it...
74+
result = await httpbinClient.GetAsync("https://httpbin.com/get");
75+
Check.That(result).HasResponseHeader("Server", "httpbin").And.HasHttpStatusCode(HttpStatusCode.NotFound);
76+
77+
// Now assert every TestableHttpMessageHandlers to make sure we made the requests.
78+
testableGithubHandler.ShouldHaveMadeRequestsTo("https://github.com/*");
79+
testableHttpBinHandler.ShouldHaveMadeRequestsTo("https://httpbin.com/*");
80+
}
81+
82+
[Fact]
83+
public async Task ConfigureViaConfigureTestServicesOnHostBuilder()
84+
{
85+
// Create TestableHttpMessageHandler as usual.
86+
var testableHttpMessageHandler = new TestableHttpMessageHandler();
87+
testableHttpMessageHandler.RespondWith(response => response.WithHttpStatusCode(HttpStatusCode.OK));
5588

56-
testableGithubHandler.ShouldHaveMadeRequests();
57-
testableHttpBinHandler.ShouldHaveMadeRequests();
89+
// Setup a TestServer
90+
using var host = await new HostBuilder()
91+
.ConfigureWebHost(webBuilder =>
92+
{
93+
webBuilder.UseTestServer()
94+
// Configure the startup class, in this case it already configures a default HttpClient
95+
.UseStartup<StartUpWithDefaultHttpHandler>()
96+
// Reconfigure the default HttpClient and set the TestableHttpMessageHandler as the primary HttpMessageHandler
97+
.ConfigureTestServices(services => services.AddHttpClient(string.Empty).ConfigurePrimaryHttpMessageHandler(() => testableHttpMessageHandler));
98+
})
99+
.StartAsync();
100+
101+
var client = host.GetTestClient();
102+
// Make a request to the testserver
103+
_ = await client.GetAsync("/");
104+
105+
// Assert that the code in the test server made the expected request.
106+
testableHttpMessageHandler.ShouldHaveMadeRequestsTo("https://httpbin.com/get");
58107
}
59108

60-
private class HttpbinClient
109+
private class StartUpWithDefaultHttpHandler
61110
{
62-
private readonly IHttpClientFactory _httpClientFactory;
63-
public HttpbinClient(IHttpClientFactory httpClientFactory)
111+
public static void ConfigureServices(IServiceCollection services)
64112
{
65-
_httpClientFactory = httpClientFactory;
113+
services.AddHttpClient();
66114
}
67115

68-
public Task<HttpResponseMessage> Get()
116+
public static void Configure(IApplicationBuilder app)
69117
{
70-
var client = _httpClientFactory.CreateClient();
71-
return client.GetAsync("https://httpbin.com/get");
118+
app.Run(async context =>
119+
{
120+
var httpClientFactory = context.RequestServices.GetRequiredService<IHttpClientFactory>();
121+
var httpClient = httpClientFactory.CreateClient();
122+
await httpClient.GetAsync("https://httpbin.com/get");
123+
await context.Response.WriteAsync("Hello");
124+
});
72125
}
73126
}
74127
}

0 commit comments

Comments
 (0)