介绍
几年前,微软引入了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
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 群星1995《摇滚中国乐势力》首版引进版[WAV+CUE][983M]
- 陈思安《32首酒廊情调》2CD新雅(国际)影碟[WAV+CUE]
- 齐豫潘越云《回声》K2HD[正版原抓WAV+CUE]
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]