Search code examples
c#.net-coredependency-injectiondelegatinghandler

Verify that my DelegatingHandler was added to IHttpClientBuilder


I have code which adds a named HttpClient to the ServiceCollection and adds a DelegatingHandler to the client. Example code:

public class MyDelegatingHandler : DelegatingHandler
{
    // ...
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHttpClient("MyClient")
                .AddHttpMessageHandler(provider => new MyDelegatingHandler());
        });

When writing unit tests, how can I verify that the DelegatingHandler implementation added was MyDelegatingHanlder?


Solution

  • This information is stored down in a private field of the HttpClient. You can get at it, but it's a tad unorthodox. So, you may or may not be interested, but I am going to throw this out there in case you are:

    public static class HttpClientExtensions
    {
        public static bool ContainsDelegatingHandler<TDelegatingHandler>(
            this HttpClient httpClient) where TDelegatingHandler: DelegatingHandler
        {
            if(httpClient == null)
            {
                throw new ArgumentNullException(nameof(httpClient));
            }
    
            var internalHandlerField = typeof(HttpMessageInvoker).GetField(
                "_handler", BindingFlags.NonPublic | BindingFlags.Instance);
            if(internalHandlerField == null)
            {
                throw new InvalidOperationException(
                    "_handler no longer exists as a private instance field of HttpClient");
            }
    
            // run down the chain of delegating handlers until there are no more
            var delegatingHandler = internalHandlerField.GetValue(httpClient) as DelegatingHandler;
            while (delegatingHandler != null)
            {
                if(delegatingHandler.GetType() == typeof(TDelegatingHandler))
                {
                    return true;
                }
                delegatingHandler = delegatingHandler.InnerHandler as DelegatingHandler;
            }
    
            return false;
        }
    }
    

    To test, you'd first have to create an HttpClient using the factory:

    var httpClient = httpClientFactory.CreateClient("MyClient");
    

    Then run it through the extension:

    if(!httpClient.ContainsDelegatingHandler<MyDelegatingHandler>())
    {
        throw new Exception(
            "HttpClient with name 'MyClient' does not contain " +
            $"{nameof(MyDelegatingHandler)} delegating handler.");
    }