Search code examples
c#moqdotnet-httpclient

While unit testing GetAsync, How to make an HttpResponseMessage returns an exception to be caught by the catch block?


I'm unit testing a code similar to the one below. There is one use case where I want the GetAsync to throw an exception to be caught in the catch block.

try
{
   var response = await client.GetAsync(url, cancellationToken);
}
catch(Exception e)
{
  _logger.LogError(e)
}

I'm mocking the HttpClient

var factory = new Mock<IHttpClientFactory>();

var httpClient = new HttpClient(handler)
{
   BaseAddress = new Uri("http://localhost:7100")
}

factory.Setup(_ => _.CreateClient(It.IsAny<string>()))
      .Returns(httpClient)
      .Verifiable();

Here I'm mocking the HttpMessageHandler

var handler = new Mock<HttpMessageHandler>();
handler
    .Protected()
    .Setup<Task<HttpResponseMessage>>(
      "SendAsync",
      ItExpr.IsAny<HttpRequestMessage>(),
      ItExpr.IsAny<CancellationToken>()
    )
    .Returns(GetHttpResponseMessage())
    .Verifiable();

GetHttpResponseMessage() is the method where I put the logic to return the appropriate HttpResponseMassage.

HttpResponseMessage GetHttpResponseMessage(int code)
{
   if(code == 200)
   {
      return new HttpResponseMessage{ StatusCode = HttpStatusCode.OK };

   }
   else if(code == 500)
   {
      //StatusCode.InternalServerError   ???
      //throw new Exception() ???
   }
}

None of those 2 above is working. Neither one is causing an exception to be caught by the catch block.

Thanks for helping


Solution

  • You can setup the async method to throw an exception directly

    using Moq;
    using Moq.Protected;
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class YourTestClass
    {
        public void TestMethod()
        {
            var factory = new Mock<IHttpClientFactory>();
    
            var handler = new Mock<HttpMessageHandler>();
            handler
                .Protected()
                .Setup<Task<HttpResponseMessage>>(
                    "SendAsync",
                    ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>()
                )
                .Throws(new HttpRequestException("Simulated exception"))
                .Verifiable();
    
            var httpClient = new HttpClient(handler.Object)
            {
                BaseAddress = new Uri("http://localhost:7100")
            };
    
            factory.Setup(_ => _.CreateClient(It.IsAny<string>()))
                  .Returns(httpClient)
                  .Verifiable();
    
            
            try
            {
               
            }
            catch (HttpRequestException ex)
            {
             
            }
        }
    }