Mocking HttpClient in Unit Tests

I’ve recently unit tested a component that uses an HttpClient object in c# .net. The methods I had to test uses HttpClient to make requests and get responses from Onvio webapi and I’ve mocked the HttpClient in a very single way and it worked just fine to me.

It requires not changing anything, but delegates the HttpClient object instantiation. When I instantiate it to regular uses I use the parameterless constructor, but when I am in the unit test I do use the constructor that requires an HttpMessageHandler object (see more details here).

I’ve made an object that inherits the object HttpMessageHandler with a delegates that is executed every time a call to the SendAsync from HttpClient method is called. Since PutAsync, GetAsync and all other methods from HttpClient object calls SendAsync behind the scenes then it works just fine for all activities in HttpClient.

 

public class MockHttpMessageHandler : HttpMessageHandler

{

public MockHttpMessageHandler(

Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> sendAsyncDelegate

)

{

this.SendAsyncDelegate = sendAsyncDelegate;

}

 

public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>>

SendAsyncDelegate { get; private set; }

 

protected override Task<HttpResponseMessage> SendAsync(

HttpRequestMessage request,

CancellationToken cancellationToken)

{

return this.SendAsyncDelegate(request, cancellationToken);

}

}

 

 

Then when unit testing I do something similar to the following code I’m sharing next.

 

 

//Arrange

HttpRequestMessage actualHttpRequestMessage = null;

var mockHttpMessageHandler = new MockHttpMessageHandler((rm, sa) =>

{

actualHttpRequestMessage = rm;

return Task<HttpResponseMessage>.Factory.StartNew(() =>

{

string jsonRequest = JsonConvert.SerializeObject(expectedResponse);

var response = new HttpResponseMessage(HttpStatusCode.Accepted);

response.Content = new StringContent(

jsonRequest, Encoding.UTF8, “application/json”);

return response;

});

});

 

var mockHttpHelper = new Mock<IHttpHelper>();

mockHttpHelper.Setup(s => s.GetHttpClient()).Returns(

new HttpClient(mockHttpMessageHandler));

 

var repository = getRepository(settingsProvider, authenticationProvider);

 

//Act

repository.HttpHelper = mockHttpHelper.Object;

actualResponseObject = DoSomethingThatCallHttpClientInside();

 

//Assert

Assert.IsNotNull(repository);

Assert.AreEqual(

actualHttpRequestMessage.Headers.Accept.ToString(),

“application/json”);

Assert.AreEqual(

actualHttpRequestMessage.RequestUri.AbsoluteUri,

expectedUrl);

Assert.AreEqual(

actualHttpRequestMessage.Headers.Authorization.ToString(),

string.Format(“UDSLongToken {0}”, tokenStorage.LongToken));

Assert.AreEqual(

actualHttpRequestMessage.Method,

httpMethod);

 

I hope it helps.