Mocking HttpClient in unit tests
November 27, 2024 by Anuraj
dotnet unittest
In this blog post, we’ll learn mock HttpClient in unit tests. Recently I started working on a C# wrapper on BlueSky API. To write the unit tests for the library, I had to mock HttpClient.
Since the HttpClient does not inherit from any interface so we will have to write our own. We can implement a custom IHttpHandler
interface like this.
public interface IHttpHandler
{
Task<HttpResponseMessage> PostAsJsonAsync<TValue>(string? requestUri, TValue value, CancellationToken cancellationToken);
//Ignoring the other method implementations.
}
And we can implement it like this.
public class HttpHandler : IHttpHandler
{
private readonly HttpClient _httpClient = new();
public async Task<HttpResponseMessage> PostAsJsonAsync<TValue>(string? requestUri,
TValue value, CancellationToken cancellationToken)
{
return await _httpClient.PostAsJsonAsync(requestUri, value, cancellationToken);
}
}
And we can use this in the library - instead of using HttpClient directly.
In my case, I am using Moq so I used different approach - where I am able to Mock the httpClient, here is an example.
var mockHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
mockHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(JsonSerializer.Serialize(createSessionResponse), Encoding.UTF8, "application/json")
});
var httpClient = new HttpClient(mockHandler.Object);
var client = new BlueSkyClient(httpClient);
await client.CreateSession("Handle", "Password");
mockHandler.Protected().Verify("SendAsync",
Times.Exactly(1),
ItExpr.Is<HttpRequestMessage>(m => m.Method == HttpMethod.Post),
ItExpr.IsAny<CancellationToken>());
This way we can mock httpClient in unit tests.
Happy Programming
Copyright © 2024 Anuraj. Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license. This is a personal blog. The opinions expressed here represent my own and not those of my employer. Powered by Jekyll. Hosted with ❤ by GitHub