22using System . Net . Http ;
33using 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
716using 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