Unit Test and mock HTTPClient with HttpMessageHandler
In this article, we will see how to Unit Test and mock HTTPClient with HttpMessageHandler using .NET Framework and .NET Core Framework.
Today in this article, we will cover below aspects,
If using in .NET Core applications it’s recommended to use HTTPClientFactory to create HTTPClient request objects.
You are using HTTPClient wrongly
HTTPClient is the most used and useful class both in .NET and .NET Core ecosystem used for calling various services like RESTFul and WebServices.
Over the years it was found that HTTPClient request objects are used in the wrong way. I have talked about the differences between HTTPClient Vs HTTPClientfactory in detail.
If using the .NET Framework or non-host apps you can use a static instance of HTTPClient. For Host Application Ex. ASP.NET Core-based apps its recommended to use HTTPClientfactory
Getting started
Below is the sample code API created we shall be unit testing and mocking.
The below code demonstrates how to mock basic HTTPClient usage which we shall be unit testing and mocking using XUnit and Moq.
[Route("api/[controller]")]
[ApiController]
public class PayController : ControllerBase
{
private static HttpClient _client ;
public PayController(HttpClient client)
{
_client = client;
}
public async Task<IActionResult> GetAccountAsyn()
{
var uri = new Uri("http://localhost:12121/account");
var response = await _client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
return Ok(response.Content.ReadAsStringAsync());
}
else
{
return StatusCode(500, "Server error");
}
}
}
Mock HTTPClient object
Mocking the HTTPClient object is all about mocking HttpMessageHandler delegates.
Mocking HttpMessageHandler will also ensure the client calling actual endpoints are faked by intercepting it.
Mock HttpMessageHandler as below,
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("{'name':thecodebuzz,'city':'USA'}"),
});
Create an HTTPClient object using above mocked HttpMessageHandler
var client = new HttpClient(mockHttpMessageHandler.Object)
{
BaseAddress = new Uri("http://test.com/")
};
The above base address is just a mock URL and it won’t impact the test cases anyway.
Here below is the complete method,
Other references:
That’s all! Happy coding!
Does this help you fix your issue?
Do you have any better solutions or suggestions? Please sound off your comments below.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.