2
votes

I am using Moq for writing tests and am able to mock the HttpClientHandler for the GetAsync() call but when I try to mock a PostAsync() it returns null. Is there a way to mock that functionality without creating a wrapper around the whole HttpClient?

Below is my unit test code for mocking the function.

Mock<WebProxy> mockWebProxy = new Mock<WebProxy>();
        mockWebProxy.Object.Address = new Uri(configuration.GetSection("TestProxy").Value);
        mockWebProxy.Object.UseDefaultCredentials = true;
        Mock<HttpClient> mockHttpClient = new Mock<HttpClient>();
        var mockHttpClientHandler = new Mock<HttpClientHandler>();
        mockHttpClientHandler.Object.Proxy = mockWebProxy.Object;
        mockHttpClientHandler
            .Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>()
            )
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("this is a test")
            })
            .Verifiable();
        mockHttpClient = new Mock<HttpClient>(mockHttpClientHandler.Object, true);

Then here is me calling the PostAsync():

var response = await httpClient.PostAsync(new Uri(url), stringContent);

The PostAsync() works when not mocking the httpClient. But when mocking, the response above is null. That tells me the mocked HttpClient is being used since there is no response but I am not sure why it is null and not the HttpResponseMessage I mocked which works for GetAsync().

1
Shouldn't you have "PostAsync" instead of "SendAsync" in your setup method? - Michiel Bugher
Unfortunately PostAsync does not exist in that context. - Ben
Configure and run integration would probably take same amount of time and will provide "real" test for the behaviour of you code. ;) - Fabio

1 Answers

1
votes

You're going to need a wrapper.

Your setup is for SendAsync which is virtual in the base HttpMessageInvoker class and so overridable, but you're calling PostAsync, which is public and not overridable.

Cool thing about HttpClient is once you wrap it you can reuse. Jut bite the bullet (if you can) and wrap it. :-)