Search code examples
c#unit-testingmockinghttpclientxunit

How to mock Httpclient inside method using xunit c#


I am trying to mock Httpclient which is created inside a method with using keyword Please see the following sample.

Public string testmethod(){

Using(Httpclient client = new Httpclient (){
Var content = "some content"
String url = "xxxx"
Client.defaultrequestheader(key,value);
Var response = client.postasync(uri,content)
})
}

How can I mock the above most of the scenario Httpclient is getting initialised at constructor.


Solution

  • You are creating new instance of HttpCLient with new keyword, introducing hard dependency on said class and this cannot be mocked.

    You have some options to mock HttpClient, but you need to use IHttpClientFactory in order to mock it:

    • use DI - so define constructor with IHttpClientFactory, that will be injected and use `Create method to get the client,
    • pass instance of IHttpClientFactory to the method as parameter, and then create the client using it

    In both options, you will be able to mock Create method - so you can return mocked HttpClient from it.

    In order to mock the client, refer to code below

    var mockMessageHandler = new Mock<HttpMessageHandler>();
    mockMessageHandler.Protected()
        .Setup<Task<HttpResponseMessage>>(
            "SendAsync", 
            ItExpr.IsAny<HttpRequestMessage>(), 
            ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage 
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("test content")
        });
    var underTest = new SiteAnalyzer(new HttpClient(mockMessageHandler.Object));
    

    Just use appropriate, desired values here:

    new HttpResponseMessage 
    {
        StatusCode = HttpStatusCode.OK,
        Content = new StringContent("test content")
    }
    

    For explanation and full discussion see this SO post - Mocking HttpClient in unit tests.