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 = "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

相关文章

  • asp.net Coolite 学习交流

    asp.net Coolite 学习交流

    近来不知什么原因,发现国人有不少开始学习Coolite了,对于有些人可能不知道什么是Coolite,这里先简单介绍一下
    2009-05-05
  • asp.net利用反射实现给model类赋值的方法

    asp.net利用反射实现给model类赋值的方法

    这篇文章主要介绍了asp.net利用反射实现给model类赋值的方法,结合实例形式分析了asp.net使用反射给model类赋值的操作步骤与相关操作技巧,需要的朋友可以参考下
    2017-03-03
  • Asp.net Core Jenkins Docker实现一键化部署的实现

    Asp.net Core Jenkins Docker实现一键化部署的实现

    这篇文章主要介绍了Asp.net Core Jenkins Docker实现一键化部署的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • js与ASP.NET 中文乱码问题

    js与ASP.NET 中文乱码问题

    本文摘自一位哥们的QQ空间里,自认为方案比较可行,也确实解决了开发中的这一类问题,非原创,写在此是为以后自己能方便的找到,也希望对其他的朋友有帮助。
    2009-10-10
  • ASP.NET中图片显示方法实例

    ASP.NET中图片显示方法实例

    这篇文章主要介绍了ASP.NET中图片显示方法,实例分析了ASP.NET图片显示所涉及的图片路径、缩略图及更新数据库图片浏览次数等相关技巧,需要的朋友可以参考下
    2015-07-07
  • .NET使用DinkToPdf将HTML转成PDF的示例代码

    .NET使用DinkToPdf将HTML转成PDF的示例代码

    这篇文章主要介绍了.NET使用DinkToPdf将HTML转成PDF的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • VS2019中.NET如何实现打日志功能

    VS2019中.NET如何实现打日志功能

    本文主要介绍了VS2019中.NET如何实现打日志功能,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • asp.net截屏功能实现截取web页面

    asp.net截屏功能实现截取web页面

    这篇文章主要介绍了asp.net截屏功能实现截取web页面,是非常实用的一个功能,需要的朋友可以参考下
    2014-08-08
  • 详解Asp.net web.config customErrors 如何设置

    详解Asp.net web.config customErrors 如何设置

    这篇文章主要介绍了详解Asp.net web.config customErrors 如何设置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • Gridview使用CheckBox全选与单选采用js实现同时高亮显示选择行

    Gridview使用CheckBox全选与单选采用js实现同时高亮显示选择行

    Gridview使用CheckBox单选与全选功能再次进行简单演示,选中的行,使用高亮显示,让用户一目了然看到哪一行被选择了,在项目中很实用的,开发中的朋友们可要考虑一下哦
    2013-01-01

最新评论