I have a SessionService
that has HttpClient
injected into it and is registered as a Typed Client See Microsoft example here .
I want to be able to write an integration test that I can control the responses made when the HttpClient is used.
I think that passing in a HttpMessageHandler
to the HttpClient
will allow me to intercept the request and control the response.
The problem I have is that I can't seem to add the HttpMessageHandler
to the existing HttpClientFactory
registration
// My client
public class SessionService
{
private readonly HttpClient httpClient;
public SessionService(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<Session> GetAsync(string id)
{
var httpResponseMessage = await this.httpClient.GetAsync($"session/{id}");
var responseJson = await httpResponseMessage.Content?.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Session>(responseJson);
}
}
// Live registrations
public static class HttpModule
{
public static IServiceCollection AddHttpModule(this IServiceCollection serviceCollection) =>
serviceCollection
.AddHttpClient<SessionService>()
.Services;
}
// My HttpMessageHandler which controls the response
public class FakeHttpMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
// customise response
return response;
}
}
If I try re-register the Typed Client so I can add the HttpMessageHandler
it tells me I've already registered the client and can't register it again.
public static class TestHttpModule
{
public static IServiceCollection AddTestHttpModule(this IServiceCollection serviceCollection) =>
serviceCollection
.AddHttpClient<SessionService>() // <== Errors
.AddHttpMessageHandler<FakeHttpMessageHandler>()
.Services;
}
Any ideas?
The problem is because when you register a HttpClient using Dependency Injection, it adds it to an internal HttpClientMappingRegistry
class. The fix was to remove the registration for the registry class. This allows me to re-add the Typed client and specify a HttpMessageHandler
public static class TestHttpModule
{
public static IServiceCollection AddTestHttpModule(this IServiceCollection serviceCollection) =>
serviceCollection
.AddSingleton(typeof(FakeHttpMessageHandler))
.RemoveHttpClientRegistry()
.AddHttpClient<SessionService>()
.AddHttpMessageHandler<FakeHttpMessageHandler>()
.Services;
private static IServiceCollection RemoveHttpClientRegistry(this IServiceCollection serviceCollection)
{
var registryType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
.SingleOrDefault(t => t.Name == "HttpClientMappingRegistry");
var descriptor = serviceCollection.SingleOrDefault(x => x.ServiceType == registryType);
if (descriptor != null)
{
serviceCollection.Remove(descriptor);
}
return serviceCollection;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.