C# – How to mock a Web API call with Moq

In this post, we will see how to mock a Web API call with Moq.
In order to do it, we will create some unit test for the method GetAllUsers that we used in the post C# – Use IHttpClientFactory in a console app.

OBVIOUSLY, THE METHOD IS VERY EASY, BUT WE WILL USE IT ONLY TO SEE HOW TO MOQ A WEB API CALL!

We add a new xUnit Test project and then, we will create a class called ServiceManagementTest where we will write these two tests:

[ServiceManagementTest.cs]

using MockWEBAPI;
using Moq;
using Moq.Protected;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace TestProject
{
    public class ServiceManagementTest
    {
        [Fact]
        public async Task GetAll_WithStatusCodeOk_ReturnAListOfUsers()
        {
            // Arrange

            // we create a mock of IHttpClientFactory
            var mockFactory = new Mock<IHttpClientFactory>();

            // The MessageHandler is a class that receives an HTTP request and returns an HTTP response.
            // For this reason, we create a mock of it where we define
            // the status code and the result (in this case a list of Users)
            var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
            mockHttpMessageHandler.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new StringContent("[{\"id\":1,\"username\":\"username1\", \"password\":\"password1\", \"email\":\"email1@test.com\"}," +
                    "{\"id\":2,\"username\":\"username2\", \"password\":\"password2\", \"email\":\"email2@test.com\"}, " +
                    "{\"id\":3,\"username\":\"username3\", \"password\":\"password3\", \"email\":\"email3@test.com\"}]"),
                });

            var client = new HttpClient(mockHttpMessageHandler.Object);
            // here we define the IHttpClientFactory's CreateClient method 
            mockFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(client);

            ServiceManagement objServiceManagement = new ServiceManagement(mockFactory.Object);

            // Act
            var result = await objServiceManagement.GetAllUsers();

            // Asser
            Assert.Equal(3, result.Count());
            Assert.Equal("username1", result.Where(x => x.Id == 1).FirstOrDefault().Username);
            Assert.Equal("username2", result.Where(x => x.Id == 2).FirstOrDefault().Username);
            Assert.Equal("username3", result.Where(x => x.Id == 3).FirstOrDefault().Username);
        }

        [Fact]
        public async Task GetAll_WithStatusCodeNotEqualAtOk_ReturnAListNull()
        {
            // Arrange

            // we create a mock of IHttpClientFactory
            var mockFactory = new Mock<IHttpClientFactory>();

            // The MessageHandler is a class that receives an HTTP request and returns an HTTP response.
            // For this reason, we create a mock of it where we define
            // the status code(in this case an error)
            var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
            mockHttpMessageHandler.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.InternalServerError
                });

            var client = new HttpClient(mockHttpMessageHandler.Object);
            // here we define the IHttpClientFactory's CreateClient method 
            mockFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(client);

            ServiceManagement objServiceManagement = new ServiceManagement(mockFactory.Object);

            // Act
            var result = await objServiceManagement.GetAllUsers();

            // Asser
            Assert.Null(result);
        }
    }
}



We have done and now, if we run the tests, this will be the result: