HttpClientLab turns the HttpClientFactory into a lab, so you can mock the HttpClient to write tests.
Since the introduction of
HttpClient in .NET Framework 4.5, managing its life-cycle properly has always been quite tricky, and the common approach has been to create one instance per dependency to call via the IoC container.
ASP.NET Core has been designed with dependency injection as first class concept, however a IoC container is not enough to properly manage the life-cycle of a
HttpClient. In fact, when reusing the same instance DNS changed takes too long to propagate, like if you rely on switching DNS to handle blue-green deployment you risk to not switch to the new environment.
ASP.NET Core 2.1 has finally introduced an easy way to manage your
HttpClients through a factory called
HttpClientFactory, which cache the underlying
HttpClientHandlers and reuse the connections.
ASP.NET Core also offers a built-in capability to write in-memory integration tests with the
Microsoft.AspNetCore.Mvc.Testing, however there is no support out of the box to integrate with the
HttpClientFactory to also mock the
Even if the application has a good unit test coverage, it is important to also have integration tests to make sure that all the pieces fit well together, but relying on actual http calls is both brittle and slow.
Moreover, if we also want to simulate error condition in our integration tests, we need to be able to define different behaviours of the http dependency.
Usual solutions involves creating a client class that abstract the http calls and then stub it in the integration tests, however this means loosing the ability to test this critical part of the system which, for its nature of doing the http calls, will also not be unit tested. Another approach is to integrate with a http mocking frameworks but that involve an hardworking setup and a steep learning curve.
We need to turn the
HttpClientFactory into a lab to mock the
HttpClient with very little boilerplate.
HttpClientLab is a free, open source, testing tool for the .NET Core
It is a solution to mock the behaviour of an external Http services, with an easy to use fluent interface, which reduce the amount of boiler plate required while allowing full flexibility.
To use it, when you obtain the client to call the in-memory test server from the usual
WebApplicationFactory, you specify that you want to redefine the behaviour of the
HttpClients with a single instruction:
// _factory is the WebApplicationFactory<Startup> injected into the test class
var client = _factory
.WithHttpClientBehaviour(out var httpClientBehaviour)
That’s it! It doesn’t even require to define a custom factory.
Then you can setup the behaviour of the HttpClient, choosing if you want to define the behaviour for all clients or only for a specific named or typed client.
You can then match the requests via direct access to the
HttpRequestMessage and return the desired
var gitHubClientBehaviour = httpClientBehaviour
.SetupForClient("GitHubClient") // or .SetupForClient<GitHubClient> or .SetupForAnyClient()
.ForRequest(req => req.Method == HttpMethod.Get) // direct access to the HttpRequestMessage
// or .ForAnyRequest()
.Returns(new HttpResponseMessage(HttpStatusCode.OK) // return simply a HttpResponseMessage
Content = new StringContent("Hello world!")
Moreover, this will not meddle with the
HttpClient pipeline, and any
DelegatingHandler you add in your application will still be invoked so that you can intercept whatever will be actually transferred on the wire.
The library also includes a handy helper method to print all the http requests received to simplify the debugging of failing tests:
// _output is the XUnit ITestOutputHelper
To start using it, just install the
HttpClientLab nuget package in your integration test project or look at the full example of using it for in-memory integration tests of a ASP.NET Core app here. There is also sample code on how to use it in any .NET Core app here.
HttpClientLab is available on NuGet, while the source is on GitHub.
It is licensed under Apache License 2.0.
- reduced boilerplate, for zero to a working test in seconds
- no need to learn a new syntax to define the HttpClient behaviour
- direct access to
- for advanced scenarios, can be used with your mocking framework of choice
My name is Alessio Franceschelli. I'm a software developer based in London, UK. I work as Senior Principal Engineer for Trainline but these blog's opinions are my own.