ASP.NET Core针对一个使用HttpClient对象的类编写单元测试详解
 更新时间:2019年01月04日 11:05:36   作者:Lamond Lu  

这篇文章主要给大家介绍了关于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 = “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 = “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来达到目的。
本篇源代码:github.com/lamondlu/Sample_TestHttpClient (本地下载)
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对华域联盟的支持。
原文地址: How to unit test a class that consumes an HttpClient with IHttpClientFactory in ASP.NET Core?

作者: Anthony Giretti

您可能感兴趣的文章:详解如何在ASP.NET Core中使用IHttpClientFactoryAsp.Net Core2.1前后使用HttpClient的两种方式如何在Asp.Net Core中集成ABP DapperAsp.NET Core 限流控制(AspNetCoreRateLimit)的实现在 ASP.Net Core 中使用 MiniProfiler的方法ASP.NET Core MVC解决控制器同名Action请求不明确的问题Asp.Net Core 调用第三方Open API查询物流数据的示例Asp.Net Core中创建多DbContext并迁移到数据库的步骤在ASP.NET Core中应用HttpClient获取数据和内容

core
httpclient
单元测试

相关文章
ASP.NET实现Hadoop增删改查的示例代码本篇文章主要介绍了ASP.NET实现Hadoop增删改查的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
2017-10-10
最简单的.NET生成随机数函数众所周知 .Net中Random类生成的随机数是假随机数,关键要看构造函数里的种子
2009-05-05
Amazing ASP.NET Core 2.0Amazing ASP.NET Core 2.0,这篇文章主要介绍了ASP.NET Core 2.0 版本的新特性,感兴趣的小伙伴们可以参考一下 2017-05-05
c#加密类使用方法示例这篇文章主要介绍了c#加密类使用方法,大家可以参考使用 2013-11-11
一个完整的ASP.NET 2.0 URL重写方案[翻译]这篇文章描述了一个完整的 ASP.NET 2.0 URL 重写方案。这个方案使用正则表达式来定义重写规则并解决通过虚拟 URLs 访问页面产生回发事件的一些可能的困难。 2009-11-11
discuz 跨域整合的记录文件最近我负责了从a.com,b.com,c.com同步可以登录到bbs.comDISCUZ论坛。记录下 2009-06-06
viewstate和datatable动态录入数据示例这篇文章主要介绍了viewstate和datatable动态录入数据示例,需要的朋友可以参考下 2014-02-02
asp.net的加密解密技巧这篇文章主要介绍了Asp.net的加密解密技巧,需要的朋友可以参考下 2015-10-10
使用vs2019加.net core 对WeiApi的创建过程详解这篇文章主要介绍了使用vs2019加.net core 对WeiApi的创建,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 2020-07-07
ASP.NET递归法求阶乘解决思路递归就是在过程或函数里调用自身,在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序 2012-12-12

最新评论

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。