Home > Software engineering >  Mocking HttpClient in xunit for different endpoint
Mocking HttpClient in xunit for different endpoint

Time:12-30

I am mocking HttpClient for unit testing following this SO suggestion. It works as expected for a single endpoint, and I am wondering how I can adjust it for a different endpoint. Please see the following sample:

class Agent
{
    private HttpClient _client;
    private string _baseUri = "http://example.com/";
    public Agent(HttpClient client)
    { _client = client; }

    public bool Run()
    {
        var res1 = client.GetAsync(new Uri(_baseUri, "endpoint1"));
        var res2 = client.GetAsync(new Uri(_baseUri, "endpoint2"));
        return res1 == res2
    }
}

// In the test method:
var responseMessage = new HttpResponseMessage
{
    StatusCode = HttpStatusCode.OK,
    Content = new StringContent("test_return")
};

var mock = new Mock<HttpMessageHandler>();
mock.Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(responseMessage);

client = new HttpClient(mock.Object);

var agent = new Agent(client);
var resp = agent.Run();

Assert.True(resp)

In the above example, resp will be always true because as a result of mocking, the response from both endpoints in the Run method will be equal.

CodePudding user response:

I think that you must setup 2 "sendasync" call. As in

Warning code not tested !

// response to /endpoint1
        var responseMessage1 = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("test_return")
        };
        
        // response to /endpoint2
        var responseMessage2 = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("test_other_return")
        };
        
        var mock = new Mock<HttpMessageHandler>();
        

        // mock a call to /endpoint1
        mock.Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                It.Is<HttpRequestMessage>(m => m.RequestUri.AbsolutePath.Contains("endpoint1")), 
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(responseMessage1);
        
        // mock a call to /endpoint2
        mock.Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                It.Is<HttpRequestMessage>(m => m.RequestUri.AbsolutePath.Contains("endpoint2")), 
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(responseMessage2);
        
        var client = new HttpClient(mock.Object);
        
        var agent = new Agent(client);
        var resp = agent.Run();

  • Related