Recently I was investigating the performance of systems, and a lot of the issues kept coming back to the same core issue: http calls to other services.

In an absolutely ideal world each of our microservices would own all of the data that they require to function, but this isn’t always the case, and sometimes you need to store data in an appropriate repository, e.g. Azure Blob Storage or AWS S3. In these circumstances there is an inevitability about the need to make http calls.

In reviewing all of this code making http calls, one striking thing jumped out at me, none of the code that made use of HttpClient was unit tested. There was some effort at integration testing, though thanks to the complexity of the systems involved this was, at best, piecemeal.

So I started investigating, trying to find a sensible description of how to test code that made use of HttpClient, and I’ll be honest I found precisely one (yes, 1) article. And now I cannot find that article. So here for posterity is a (quick) walkthrough of how I began to rectify the situation.

What is a DelegatingHandler?

Luckily the concept to unit testing code that makes use of HttpClient is very simple, and is rooted in the way that HttpClient is designed. We’re going to create a simple DelegatingHandler and inject that into our HttpClient. Steve Gordon has an excellent article that discusses the internals of HttpClient - HttpClientFactory In Asp.Net Core 2.1 (Part 3) - Outgoing Request Middleware With Handlers.. I cannot recommend this set of articles highly enough, and even though they were written in 2018 they are still relevant now. I strongly recommend reading the article on DelegatingHandlers before finishing this article.

Instead of passing control back to the base class as Steve demonstrated in his article, our stub will directly return a suitable response, creating a stack like so:

Modified outgoing request pipeline

The code to create the stub delegating handler is very simple and straight forward:

internal class OkMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
    }
}

It’s a simple task of creating a class that inherits from DelegatingHandler and providing an implementation of SendAsync.

Use of the stub delegating handler is as straightforward, though slightly less intuitive. We do this via the HttpClient constructor:

var httpClient = new HttpClient(new OkMessageHandler());

Then we get the system under test to use our HttpClient:

The InternetCaller demonstrates (after a fashion) how to use a directly provided HttpClient or creating one using IHttpClientFactory.