ASP.NET Core Web API 集成测试

发表于:2019-3-15 13:45

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:solenovex    来源:博客园

  集成测试 vs 单元测试
  测试金字塔, 但它只是一个指导性的概念.
  如果所单元测试是对一个组件进行隔离测试的话, 那么集成测试则是测试多个组件共同协作产生出期待的结果.
  单元测试通常很快. 而集成测试则慢的多, 因为它需要很多配置, 并且可能依赖于外部的组件, 例如数据库, 网络, 文件等.
  通常在一个项目里单元测试要比集成测试多很多.
  单元测试通常依赖于mock的组件, 而集成测试则使用可运行的组件.
  注意: 如果一个行为可以通过单元测试或集成测试来测试的话, 那么应该使用单元测试.
  如何进行集成测试
  如果我想测试一个API Controller的Action, 我可能需要把这个项目运行起来, 等它跑起来, 发送请求并检验结果. 但这样做的话需要很多的配置工作, 并且很麻烦.
  幸好ASP.NET Core 提供了一个Microsoft.AspNetCore.TestHost 库, 使用它就无需单独去运行被测试系统了.
  ASP.NET Core应用里, 我们在Program.cs里创建WebHostBuilder, 并配置Kestrel Web服务器, 使用Startup类进行应用配置, 注册服务和中间件等. 最终在WebHostBuilder上使用Build()来创建WebHost的实例, 它可以用来在特定的URL和端口上运行并监听请求.
  而这个TestHost库也使用了WebHostBuilder, 但它会自己把构建和运行web宿主的工作处理好, 也就是创建出了一个TestServer. TestServer不会在网络上进行监听, TestServer创建了一个名为Host的属性, 它的类型是IWebHost, 它可以用来处理内存里的请求对象. TestServer还会暴露一个HttpClient, 你可以用它来发送请求到被测试系统. 整个交互的过程都是在内存里完成的.
  下图是被测试系统在生产环境和集成测试使用TestServer情形下的对比图:
  图中:
  当应用/被测试系统在生产环境运行的时候, 它使用Kestrel服务器, 监听HTTP请求, 并把它转化为HttpContext, 然后再传进ASP.NET Core的管道里.
  TestServer不监听网络请求, 它使用HttpClient在内存里发送请求.
  仔细看一下集成测试时使用TestServer的流图:
  图中可以看到: 测试代码创建TestServer, TestServer创建HttpClient. 测试代码使用HttpClient发送请求接收响应. TestServer会转化请求并交给ASP.NET Core MVC/API 应用来处理.
  一个例子
  首先需要为你的应用建立集成测试项目:
  然后需要为项目添加Microsoft.AspNetCore.TestHost 这个库:
  被测试的是这个Controller的GetRoot()所对应的行为, 而不只是这个方法:
  测试返回NoContent:
  这里面按照之前讲的顺序, 创建IWebHostBuilder, 并用它创建TestServer, 然后TestServer创建HttpClient. 随后就使用httpClient发送请求, 返回结果, Assert即可.
  需要注意的是, 在创建IWebHostBuilder的时候, 我使用了被测试系统的Startup类来进行配置, 并设定的环境是Development.
  由于我这个项目可以看作是真实项目, 所以第一次运行该测试的时候, 测试是Fail的. 因为Startup里面有很多配置并不满足测试要求.
  在我把IpRateLimiting, HttpsRedirection, Authentication, AuthorizeFilter等中间件/组件去掉之后, 测试才通过:
  所以这就引出了一个问题, Startup里面的配置在开发时 和 测试时 以及 生产运行时 可能是不太一样的.
  我的Startup里面已经有很多代码了, 如果再进行环境判断, 那就会更乱了.
  所以我决定为集成测试新建立一个Startup配置类:
  ASP.NET Core项目也支持多环境的多个Startup配置类, 这部分内容请参考官方文档: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.1#environment-based-startup-class-and-methods.
  然后修改代码, 使用这个测试专用的Startup即可:
  测试会通过.
  被测试系统有依赖项
  下面继续测试GetRoot方法的另一个路径, 这个路径会用到RootController的依赖项IUrlHelper.
  在集成测试里, 通常情况下是不使用Mocking技术的. 所以在这里我也不会mock IUrlHelper:
  这里没有mock任何东西. 此外这个被测试的行为需要设置AcceptHeader.
  测试会Pass的, TestServer帮我搞定了一切:
  优化测试配置
  写了两个测试方法, 又引出了一个新的问题: 这两个方法有一些共同的设置代码, 这些设置可能会比较耗资源. 我们可以把这些设置放在构造函数里面, 但是如果使用Theory并含有多个InlineData的话, 就会多次运行构造函数里的设置代码, 可能会非常好资源(时间).
  所以我们应该考虑使用test fixture 这里有介绍: http://www.cnblogs.com/cgzl/p/8438019.html#share
  而且我们可以使用WebApplicationFactory来构建TestServer, 使用WebApplicationFactory的好处是可以灵活的进行自定义配置.
  要使用WebApplicationFactory, 需要添加库: Microsoft.AspNetCore.Mvc.Testing
  使用该库之后, 代码应该如下:

       上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
  
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号