简体   繁体   中英

When using HttpClientFactory in c#, how can I test the Http call being made?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM