相信大家对如何在ASP.NETCore中编写单元测试很感兴趣,在本文中,我们将一步一步详细记录案例、步骤和过程。希望你能从这篇文章中看到一些收获。
几年前,微软推出了HttpClient类代替HttpWebRequest来发送Web请求。这个新类更容易使用,更简洁,更异步,易于扩展。
HttpClient类有一个可以接受HttpMessageHandler类对象的构造函数。HttpMessageHandler类对象可以接受请求(HttpRequestMessage)并返回响应(HttpResponseMessage)。它的功能完全取决于它的实现。默认情况下,HttpClient使用HttpClientHandler,这是一个向网络服务器发送请求并从服务器返回响应的处理程序。在这篇博文中,我们将通过继承DelegatingHandler来创建我们自己的HttpMessageHandler。
要实现上述功能,不能直接使用HttpClient对象,需要与允许使用IHttpClientFactory接口进行模拟的依赖注入一起使用。
让我们伪造一个HttpMessageHandler。
public class FakeHttpMessageHandler : DelegatingHandler
{
private HttpResponseMessage _fakeResponse;
public FakeHttpMessageHandler(HttpResponseMessage responseMessage)
{
_fakeRespOnse= responseMessage;
}
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await Task.FromResult(_fakeResponse);
}
}
在下面的例子中,我们只讨论HttpResponseMessage,不处理HttpRequestMessage。
下面是一个伪造的HttpMessageHandler对象。
在这里,我添加了一个需要HttpResponseMessage的构造函数,然后复制了SendAsync方法,其中直接返回了构造函数中传递的HttpResponseMessage对象。
编写一个使用IHttpClientFactory接口的服务。
public class UserService
{
private readonly IHttpClientFactory _httpFactory;
public UserService(IHttpClientFactory httpFactory)
{
_httpFactory = httpFactory;
}
public async Task> GetUsers(string url)
{
using (HttpClient httpclient = _httpFactory.CreateClient())
{
using (HttpResponseMessage respOnse= await httpclient.GetAsync(url))
{
if (response.StatusCode == HttpStatusCode.OK)
{
List users = await response.Content.ReadAsAsync>();
return users;
}
return null;
}
}
}
}
接下来,我们需要编写一个UserService类,它提供了一个GetUsers方法来从远程服务器获取用户列表。
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
如您所见,使用HttpClientFactory允许我们模拟HttpClient的实例化。
public class UserServiceTests
{
[Fact]
public async Task WhenACorrectUrlIsProvided_ServiceShouldReturnAlistOfUsers()
{
// Arrange
var users = new List
{
new User
{
FirstName = "John",
LastName = "Doe"
},
new User
{
FirstName = "John",
LastName = "Deere"
}
};
var httpClientFactoryMock = Substitute.For();
var url = ";;
var fakeHttpMessageHandler = new FakeHttpMessageHandler(new HttpResponseMessage() {
StatusCode = HttpStatusCode.OK,
COntent= new StringContent(JsonConvert.SerializeObject(users), Encoding.UTF8, "application/json")
});
var fakeHttpClient = new HttpClient(fakeHttpMessageHandler);
httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
// Act
var service = new UserService(httpClientFactoryMock);
var result = await service.GetUsers(url);
// Assert
result
.Should()
.BeOfType>()
.And
.HaveCount(2)
.And
.Contain(x => x.FirstName == "John")
.And
.Contain(x => x.LastName == "Deere")
.And
.Contain(x => x.LastName == "Doe");
}
}
测试服务。
在下面的单元测试中,我们将使用XUnit、FluentAssertion和NSubstitute。
测试场景1:模拟一个请求,返回2个用户。
在上面的测试中,我们期望得到一个成功的响应,得到两个用户的信息。
我们希望从该服务获得的数据是JSON格式的。
我们使用一个伪处理程序来初始化一个HttpClient对象,然后定义这个伪对象httpClientFactoryMock。createClient()。返回(fakehttpclient)。
测试场景2:模拟一个404错误并返回空数据。
public class UserServiceTests
{
[Fact]
public async Task WhenABadUrlIsProvided_ServiceShouldReturnNull()
{
// Arrange
var httpClientFactoryMock = Substitute.For();
var url = ";;
var fakeHttpMessageHandler = new FakeHttpMessageHandler(new HttpResponseMessage() {
StatusCode = HttpStatusCode.NotFound
});
var fakeHttpClient = new HttpClient(fakeHttpMessageHandler);
httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
// Act
var service = new UserService(httpClientFactoryMock);
var result = await service.GetUsers(url);
// Assert
result
.Should()
.BeNullOrEmpty();
}
}
类似于测试场景1,当Http请求返回NotFound时,其结果集为空。
不知道你看完之后是什么感受?有没有获得什么新知识,完成自己的操作?希望以后大家支持我们的网站。这里有很多信息,会让你大饱眼福。