ASP.NET Core针对一个使用HttpClient对象的类编写单元测试详解
介绍
几年前,微软引入了HttpClient类来替代HttpWebRequest来发送Web请求。这个新的类更易于使用,更加简洁,更具有异步性,且易于扩展。
HttpClient类有一个可以接受HttpMessageHandler类对象的构造函数。HttpMessageHandler类对象可以接受一个请求(HttpRequestMessage), 并返回响应(HttpResponseMessage)。它的功能完全取决于它的实现。默认情况下HttpClient使用的是HttpClientHandler,HttpClientHandler是一个处理程序,它向网络服务器发送请求并从服务器返回响应。在本篇博文中,我们将通过继承DelegatingHandler来创建自己的HttpMessageHandler。
为了实现以上功能,HttpClient对象不可以直接使用,而是需要与允许使用IHttpClientFactory接口进行模拟的依赖注入一起使用。
让我们来伪造一个HttpMessageHandler
下面的例子中,我们只讨论HttpResponseMessage, 不会处理HttpRequestMessage。
以下是我伪造的一个HttpMessageHandler对象。
public class FakeHttpMessageHandler : DelegatingHandler { private HttpResponseMessage _fakeResponse; public FakeHttpMessageHandler(HttpResponseMessage responseMessage) { _fakeResponse = responseMessage; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return await Task.FromResult(_fakeResponse); } }
这里我添加了一个需要HttpResponseMessage构造函数,然后复写了SendAsync方法, 在该方法中直接返回了构造函数中传入的HttpResponseMessage对象。
编写一个使用IHttpClientFactory接口的服务
下面我们需要编写一个UserService类,这个类提供了一个GetUsers方法,来从远程服务器端获取用户列表。
public class UserService { private readonly IHttpClientFactory _httpFactory; public UserService(IHttpClientFactory httpFactory) { _httpFactory = httpFactory; } public async Task<List<User>> GetUsers(string url) { using (HttpClient httpclient = _httpFactory.CreateClient()) { using (HttpResponseMessage response = await httpclient.GetAsync(url)) { if (response.StatusCode == HttpStatusCode.OK) { List<User> users = await response.Content.ReadAsAsync<List<User>>(); return users; } return null; } } } }
以下是Api请求返回的用户类
public class User { public string FirstName { get; set; } public string LastName { get; set; } }
如你所见,使用HttpClientFactory允许我们模拟HttpClient实例化
测试服务
在下面的单元测试中,我们会使用XUnit、FluentAssertion、NSubstitute
测试场景1: 模拟一个请求,返回2个用户
public class UserServiceTests { [Fact] public async Task WhenACorrectUrlIsProvided_ServiceShouldReturnAlistOfUsers() { // Arrange var users = new List<User> { new User { FirstName = "John", LastName = "Doe" }, new User { FirstName = "John", LastName = "Deere" } }; var httpClientFactoryMock = Substitute.For<IHttpClientFactory>(); var url = "http://good.uri"; 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<List<User>>() .And .HaveCount(2) .And .Contain(x => x.FirstName == "John") .And .Contain(x => x.LastName == "Deere") .And .Contain(x => x.LastName == "Doe"); } }
- 在以上测试中,我们期望获取一个成功的响应,并得到2个用户的信息。
- 我们期望从Service中得到的数据是JSON格式的。
- 我们使用一个伪造的处理程序初始化了一个HttpClient对象,然后定义了我们期望的得到的伪造对象httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
测试场景2: 模拟一个404错误,返回空数据
public class UserServiceTests { [Fact] public async Task WhenABadUrlIsProvided_ServiceShouldReturnNull() { // Arrange var httpClientFactoryMock = Substitute.For<IHttpClientFactory>(); var url = "http://bad.uri"; 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请求返回Not Found, 它的结果集是Null
总结
本篇作者讲解了在ASP.NET Core中如何伪造HttpClient来测试持有HttpClient对象的类。这里主要是通过伪造的DelegatingHandler对象来创建一个HttpClient对象,并使用IHttpClientFactory来获取伪造的HttpClient来达到目的。
本篇源代码:https://github.com/lamondlu/Sample_TestHttpClient (本地下载)
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对猪先飞的支持。
原文地址: How to unit test a class that consumes an HttpClient with IHttpClientFactory in ASP.NET Core?
作者: Anthony Giretti
相关文章
- 这篇文章主要介绍了解决@SpringBootTest 单元测试遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-14
- 这篇文章主要介绍了.NET Core下使用Kafka的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了详解.NET Core 3.0 里新的JSON API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
ASP.NET Core根据环境变量支持多个 appsettings.json配置文件
这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
C#中HttpWebRequest、WebClient、HttpClient的使用详解
这篇文章主要介绍了C#中HttpWebRequest、WebClient、HttpClient的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25详解ASP.NET Core 中基于工厂的中间件激活的实现方法
这篇文章主要介绍了ASP.NET Core 中基于工厂的中间件激活的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22- Underscore 是一个 JavaScript 工具库,它提供了一整套函数式编程的实用功能,但是没有扩展任何 JavaScript 内置对象。这篇文章主要介绍了underscore源码分析相关知识,感兴趣的朋友一起学习吧...2016-01-02
详解.NET Core 使用HttpClient SSL请求出错的解决办法
这篇文章主要介绍了.NET Core 使用HttpClient SSL请求出错的解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22java HttpClient传输json格式的参数实例讲解
这篇文章主要介绍了java HttpClient传输json格式的参数实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-22.net EF Core专题:EF Core 读取数据时发生了什么?
这篇文章主要介绍了EF Core 读取数据的的相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2021-09-22- 这篇文章主要介绍了详解ASP.NET Core Token认证,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2021-09-22
- .net core是最近讨论频率很高的话题,下面这篇文章主要给大家介绍了关于利用.NET Core如何获取操作系统中各种信息的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧...2021-09-22
- 这篇文章主要介绍了asp.net core MVC之实现基于token的认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-07
- 这篇文章主要介绍了ASP.NET Core如何注入多个服务实现类的相关资料,需要的朋友可以参考下面文章的具体内容...2021-09-22
- 这篇文章主要介绍了ASP.NET Core使用JWT认证授权的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
ASP.NET core Web中使用appsettings.json配置文件的方法
这篇文章主要给大家介绍了在ASP.NET core Web中使用appsettings.json配置文件的方法,文中给出了详细的示例代码,需要的朋友可以参考学习,下面来一起看看吧。...2021-09-22- 这篇文章主要介绍了JavaWeb实战之编写单元测试类测试数据库操作,文中有非常详细的代码示例,对正在学习javaweb的小伙伴们有很大的帮助,需要的朋友可以参考下...2021-04-22
- 这篇文章主要介绍了详解EFCore中的导航属性的相关资料,帮助大家更好的理解和学习使用ASP.NET CORE,感兴趣的朋友可以了解下...2021-09-22
- 这篇文章主要介绍了Springboot 使用具体化类和配置来缩短单元测试时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-11-05