Mocking the HttpClient in .NET Core (with NSubstitute)
Tags: dotnet, testing, unittest
Published: 2019-06-16 12:03:10

---
title: Mocking the HttpClient in .NET Core (with NSubstitute)
published: true
description: Sometimes mocking certain dependencies can be hard. This post helps with mocking the HttpClient in .NET
tags: dotnet, testing, unittest
cover_image: https://thepracticaldev.s3.amazonaws.com/i/kz7g4vtm7xsz9q14icwm.jpg
---

## The problem

I was writing a client library for a webservice. Inside of the client I used the Microsoft `HttpClient` class to call the webservice. So, no magic really.
In our company, we write tests for almost all of the code that we write. That's pretty awesome on the one hand, but can be quite difficult sometimes.

I was writing unit tests, which means I didn't want to call the real service. For this reason, I needed to fake the response of the webservice. When you are working with the `HttpClient`, this means mocking the returned value of the `HttpClient.SendAsync()` method.
We are using [.NET Core](https://dotnet.microsoft.com/download) 2.2, [xUnit.net](https://xunit.net/) and [NSubstitute](https://nsubstitute.github.io/).
Using this setup, the code would normally look something like this:

```csharp
var clientMock = Substitute.For<HttpClient>();
clientMock.SendAsync(Arg.Any<HttpRequestMessage>())
    .Returns(Task.FromResult(new HttpResponseMessage
    {
        Content = new StringContent("Stuff I want to return"),
        StatusCode = HttpStatusCode.OK
    }));
var myObject = new MyObject(clientMock);
var result = myObject.DoStuff();
Assert.Equal("Some result", result.SomeProperty);
```

If you are familiar with [NSubstitute](https://nsubstitute.github.io/), you might have spotted the problem already. It is the second line, that is the problem. 
[NSubstitute](https://nsubstitute.github.io/) is calling the specific method and reconfiguring the returned value. 
So the `SendAsync` method is called with `null` as the parameter. And, who would have thought it, you must not request a empty (or null) `HttpRequestMessage`, because you don't have
an URL, or anything else. This means, already the setup of the mock throws an exception.

So, how do I mock the response then?

## The solution

The `HttpMessageHandler` comes to the rescue. It's the heart of the `HttpClient` class and it does the actual handling of the requests.
You just implement a really short handwritten mock, that returns the desired response.

> But why does it have to be "handwritten"? You are using a mocking framework, aren't you?

Yes, I'm using [NSubstitute](https://nsubstitute.github.io/) as my mocking framework. And [NSubstitute](https://nsubstitute.github.io/) relies on the public interface of the classes/interfaces it creates mocks for.
Sadly, the `SendAsync` method of the `HttpMessageHandler` is `interal protected`. So [NSubstitute](https://nsubstitute.github.io/) is not able to mock it. :-(

> Just use Moq. It's a great tool as well.

Yes, [Moq](https://github.com/Moq/moq4/wiki/Quickstart) is pretty cool as well. But because we are using [NSubstitute](https://nsubstitute.github.io/) in every project, it's not really an option to change the mocking library, if the problem can be solved with a few extra lines of code. 
That's why I had to create a handwritten mock.

The simplest version of the mock would look like this:

```csharp
public class MockHttpMessageHandler : HttpMessageHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        return new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("my string, that needs to be returned")
        };
    }
}
```


Of course, this now just works for a single test / a single return value. If you need to mock multiple return values, I have a simple solution.

```csharp
public class MockHttpMessageHandler : HttpMessageHandler
{
    private readonly string _response;

    public MockHttpMessageHandler(string response)
    {
        _response = response;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        return new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(_response)
        };
    }
}
```

Maybe you also want to control the returned status code from inside your tests.

```csharp
public class MockHttpMessageHandler : HttpMessageHandler
{
    private readonly string _response;
    private readonly HttpStatusCode _statusCode;

    public MockHttpMessageHandler(string response, HttpStatusCode statusCode)
    {
        _response = response;
        _statusCode = statusCode;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        return new HttpResponseMessage
        {
            StatusCode = _statusCode,
            Content = new StringContent(_response)
        };
    }
}
```

The last tweak that you might need is the ability to check the passed request object/request content and the number of times the method was invoked. Therefore I just put the `Content` and the `Number of calls` into a public property,
which you can use for your assertions in the test.

```csharp
public class MockHttpMessageHandler : HttpMessageHandler
{
    private readonly string _response;
    private readonly HttpStatusCode _statusCode;

    public string Input { get; private set; }
    public int NumberOfCalls { get; private set; }

    public MockHttpMessageHandler(string response, HttpStatusCode statusCode)
    {
        _response = response;
        _statusCode = statusCode;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        NumberOfCalls++;
        if (request.Content != null) // Could be a GET-request without a body
        {
            Input = await request.Content.ReadAsStringAsync();
        }
        return new HttpResponseMessage
        {
            StatusCode = _statusCode,
            Content = new StringContent(_response)
        };
    }
}
```

Simple and functional.
Now you can create the HttpClient in your test and hand it an instance of you MockHttpMessageHandler into the constructor.

## (My) final version

My final test(s) look like this:

```csharp
[Fact]
public async Task TestMyObjectDoStuff()
{
    var messageHandler = new MockHttpMessageHandler("TEST VALUE", HttpStatusCode.OK);
    var httpClient = new HttpClient(messageHandler);
    var sut = new MyObject(httpClient);

    var result = await sut.DoStuff("maybe some input");

    Assert.Equal("TEST VALUE", result.SomeProperty);
    Assert.Equal("maybe some input", messageHandler.Input);
    Assert.Equal(1, messageHandler.NumberOfCalls);
}   
```

The test now checks if the messageHandler was called with the correct value and that the client wraps the response correctly.

If you want to see a full example of this, check out the following GitHub repo: https://github.com/n-develop/HttpClientMock

What do you think about this approach? Are you doing the same thing or do you have a completely different way of dealing with this problem? Let me know in the comments.