How to mock the new HttpClientFactory in .NET Core 2.1 using Moq

The HttpClientFactory is derived from IHttpClientFactory Interface So it is just a matter of creating a mock of the interface

var mockFactory = new Mock<IHttpClientFactory>();

Depending on what you need the client for, you would then need to setup the mock to return a HttpClient for the test.

This however requires an actual HttpClient.

var clientHandlerStub = new DelegatingHandlerStub();
var client = new HttpClient(clientHandlerStub);

mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);

IHttpClientFactory factory = mockFactory.Object;

The factory can then be injected into the dependent system under test when exercising the test.

If you do not want the client calling actual endpoints then you will need to create a fake delegate handler to intercept the requests.

Example of the handler stub used to fake the requests

public class DelegatingHandlerStub : DelegatingHandler {
    private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> _handlerFunc;
    public DelegatingHandlerStub() {
        _handlerFunc = (request, cancellationToken) => Task.FromResult(request.CreateResponse(HttpStatusCode.OK));
    }

    public DelegatingHandlerStub(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> handlerFunc) {
        _handlerFunc = handlerFunc;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _handlerFunc(request, cancellationToken);
    }
}

Taken from an answer I gave here

Reference Mock HttpClient using Moq

Suppose you have a controller

[Route("api/[controller]")]
public class ValuesController : Controller {
    private readonly IHttpClientFactory _httpClientFactory;

    public ValuesController(IHttpClientFactory httpClientFactory) {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet]
    public async Task<IActionResult> Get() {
        var client = _httpClientFactory.CreateClient();
        var url = "http://example.com";
        var result = await client.GetStringAsync(url);
        return Ok(result);
    }
}

and wanted to test the Get() action.

public async Task Should_Return_Ok() {
    //Arrange
    var expected = "Hello World";
    var mockFactory = new Mock<IHttpClientFactory>();
    var configuration = new HttpConfiguration();
    var clientHandlerStub = new DelegatingHandlerStub((request, cancellationToken) => {
        request.SetConfiguration(configuration);
        var response = request.CreateResponse(HttpStatusCode.OK, expected);
        return Task.FromResult(response);
    });
    var client = new HttpClient(clientHandlerStub);
    
    mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);
    
    IHttpClientFactory factory = mockFactory.Object;
    
    var controller = new ValuesController(factory);
    
    //Act
    var result = await controller.Get();
    
    //Assert
    result.Should().NotBeNull();
    
    var okResult = result as OkObjectResult;
    
    var actual = (string) okResult.Value;
    
    actual.Should().Be(expected);
}

Leave a Comment