0

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.

Dr. Strangelove
  • 2,725
  • 3
  • 34
  • 61

1 Answers1

1

I think that you should set up two SendAsync calls as in the following.

// 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",
        ItExpr.Is<HttpRequestMessage>(
            m => m.RequestUri.AbsolutePath.Contains(
                "endpoint1")), 
        ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(responseMessage1);
        
// mock a call to /endpoint2
mock.Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.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();
Dr. Strangelove
  • 2,725
  • 3
  • 34
  • 61
Olivier Duhart
  • 362
  • 3
  • 14