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();
// Assert
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();
// Assert
Assert.Null(result);
}
}
}
We have done and now, if we run the tests, this will be the result: