本文共 5854 字,大约阅读时间需要 19 分钟。
在本文中,我们将研究如何测试你的ASP .NET Core 2.0 Web API解决方案。我们将了解使用单元测试进行内部测试,使用全新的ASP .NET Core的集成测试框架来进行外部测试。
.NET Core 最初是在 2016 年发布的,随着 .NET Core 2.0 的发布,微软拥有了下一个通用、模块化、跨平台和开源的平台主版本。.NET Core 已经创建了许多 API,在当前版本的 .net 框架中均可用。它最初是为下一代 ASP .NET解决方案而创建的,但现在成了许多其他场景的驱动和基础,包括物联网、云计算和下一代移动解决方案。在本系列文章中,我们将探讨 .NET Core 的一些好处,以及它如何不仅能使传统的 .NET 开发人员受益,还能使所有需要为市场带来健壮、高效和经济的解决方案的技术人员受益。
在使用ASP .NET Core 2.1 Web API构建并开发一组丰富的API的时候,需要记住这只是实现稳定且高效的解决方案的第一步。为你的解决方案提供一个稳定的环境是非常重要的。获得优秀的解决方案不仅需要完整地构建API,还需要严格地测试你的API,保证用户有良好的体验。
这篇文章是我之前为InfoQ写的《》的后续文章。请放心,你不需要阅读另外一篇文章,就可以从这篇文章了解到如何从测试中获得好处,但读一下那篇文章可以帮助你更多了解我是如何构建我讨论的解决方案的。在过去的几年里,我花了大量时间来思考在为客户构建API时进行测试。了解ASP .NET Core 2.1 Web API的架构,可以帮助拓宽你的了解。
本篇文章中的例子的解决方案和所有代码都可以在我的中找到。
让我们一起来快速了解一下 .NET和ASP .NET Core。ASP .NET Core是Microsoft创造的全新Web框架,以便摆脱自ASP .NET 1.0以来一直存在的遗留技术。ASP .NET Core 2.1摆脱这些遗留依赖,从头开始开发框架,因此可以给开发人员提供更高的性能,并且它是为跨平台执行而构建的。
对有些人来说,测试你的软件可能是一个新的概念,但是它很简单。我们从单元测试开始。维基百科对于它的严格定义是“是一种软件测试方法,对源代码的独立单元、一组或多组计算机程序模块以及相关的控制数据、使用程序和操作程序都进行测试,以了解它们是否适合使用”。我比较喜欢的是一个外行的解释,单元测试是保证在你添加了新的功能或进行了缺陷修复之后,你的解决方案中的代码能像预期一样执行。我们测试了一个简单的代码示例,来保证它符合我们的预期。让我们来看一下单元测试示例:
[Fact]public async Task AlbumGetAllAsync(){ // Arrange // Act var albums = await _repo.GetAllAsync(); // Assert Assert.Single(albums);}
优秀的单元测试有三个部分组成。第一个是Arrange的部分,用来设置测试中可能需要的任何资源。在上面的例子中,我没有进行任何设置,所以Arrange的部分是空的(但我还是为它保留了注释)。第二个部分是Act的部分,用来执行测试的部分。在我们的例子中,我调用数据库中的专辑实体类型,返回当前使用的库中的数据源完整的专辑实体。单元测试的最后一个部分是Assert的部分,用来验证待测试的操作是否正确。对于该测试,我检验是否从数据库中返回了一个专辑。
在本文中,我会使用xUnit工具进行单元测试。xUnit是 .NET Framework和现在的 .NET Core的开源包。我们需要 .NET Core版本的xUnit,在你安装 .NET Core 2.1 SDK的时候就已经直接获得了。你可以通过 .NET Core cli指令dotnet test,或是通过你喜欢的IDE(如Visual Studio 2017、Visual Studio Code或JetBrain的Rider.)中的项目模板来创造新的单元测试项目。
图1:在Visual Studio 2017中创建新的单元测试项目
现在,让我们深入到测试你的ASP .NET Core Web API解决方案的单元测试中来。
我非常支持使用单元测试来为你的客户保证稳定和健壮的API。但我清楚地知道要如何使用单元测试,知道要测试什么东西。我相信,你要恰到好处地对解决方案进行单元测试,而不要做多余的测试。这是什么意思呢?可能我的观点会引发很多评论,但是我不太注重要100%覆盖你的测试。我是否认为我们需要能覆盖API解决方案重要部分的测试,单独隔开每个区域,保证每个代码段都是正确的?当然!我会这么做,这也是我想要讨论的。
由于我们的示例Chinook.API很小,并且可以通过集成测试来完成测试(本文稍后讨论),我发现在Domain和Data项目中我最关注单元测试。我不会详细讨论单元测试的方法(因为这个问题超出了本文讨论的范围)。我想要让你不依赖于生产数据库的数据,从而在Domain和Data项目中进行更多的测试。这是我们下一个要讨论的问题,模拟数据和对象。
我们已经讨论了为什么我们要进行单元测试,单元测试一些什么内容。接下来,了解如何准确地单元测试ASP .NET Core Web API解决方案是非常重要的。数据是测试API的重点。测试可预测的数据集是非常重要的。这就是为什么我不推荐使用生产数据或者其他可能随着时间根据你的了解和认知会改变的数据。我们需要稳定的数据集来保证所有单元测试的运行,确保代码段之间的测试是相同的。比如说,在我测试Chinook.Domain项目的时候,我想要得到ID是42的专辑,我需要保证它的确存在,并拥有类似专辑名称这样的细节,和一条艺术家数据有关联关系。我还希望确保在我从数据源中得到一系列专辑时,大小满足我编写的单元测试。
许多业内人士使用“模拟数据”这一术语来表示这一类数据。有很多为单元测试产生模拟数据的方法,我希望你能创造出尽可能“真实”的数据集。你给测试创造的数据越好,测试效果也会越好。我会建议你确保数据没有隐私问题,不包含公司或客户的个人数据或敏感数据。
要满足我们对于干净、稳定数据的需求,我单独创建了一个项目,封装了单元测试项目的模拟数据。让我们称其为Chinook.MockData(就像你能在示例中看到的一样)。我的MockData项目几乎和Chinook.Data项目相同。它们都拥有相同数量的数据库,都和相同的接口依附。我希望MockData项目存储在依赖注入(DI) 容器中,这样Chinook.Domain项目就可以像连接到了生产数据源那样得到使用。这就是为什么我很喜欢依赖注入。它可以帮助我通过配置切换Data项目,而不需要做任何代码变更。
在我们为ASP .NET Core Web API解决方案执行并验证了单元测试之后,我们要看一个完全不同类型的测试。我希望单元测试可以验证并确保对解决方案内部组件的期望。当我们对内部测试的质量满意的时候,我们需要从外部接口进行API测试,这就是我们所说的集成测试。
集成测试需要在所有的组件完成的时候编写并执行,所以你的API可以通过正确的HTTP响应来验证。单元测试时测试的是单独隔离开的代码段,而集成测试时测试的是HTTP端点上每个API的整体逻辑。测试将会遵循API的完整工作流,从API项目的控制器到域项目管理器,最后到Data项目的库(返回来响应)。
要使用你现有的测试知识,集成测试功能是基于现有的单元测试库的。我将使用xUnit来创造我的集成测试。在我们创建了名为Chinook.IntegrationTest的新xUnit测试项目之后,我们需要添加合适的NuGet包。将Microsoft.AspNetCore.TestHost包添加到Chinook.IntegrationTest项目中来。这个包中包含了执行集成测试的资源。
图2:添加Microsoft.AspNetCore.TestHost NuGet包
接下来,我们可以创建第一个集成测试来从外部验证我们的API。
要想进行我们解决方案中的所有API外部测试,我要创建一个名为API的文件夹,其中包含了测试。我还需要在API域中给每个实体类型创建新的测试类。我们的首个集成测试将会覆盖专辑实体类型。
在API文件夹中创建新的类AlbumAPITest.cs。之后我们会在文件中添加如下的命名空间。
using Xunit;using Chinook.API;using Microsoft.AspNetCore.TestHost;using Microsoft.AspNetCore.Hosting;图3:使用指令进行集成测试
现在我们要使用TestServer来设置类,使用HttpClient来执行测试。我们需要名为_client,类型为HttpClient的私有变量,它是基于在AlbumAPITest类中的构造函数中初始化的TestServer而创建的。TestServer是小型web服务器的包装器,是基于Chinook.API Startup和需要的开发环境创建的。在这个例子中,我使用开发环境。我们现在具备了运行API的web服务器,以及了解如何在TestServer中调用API的客户端。我们可以开始编写集成测试代码了。
图4:我们第一个集成测试,获得所有的专辑
除了构造函数代码之外,图4中还展示了第一个集成测试的代码。AlbumGetAllTestAsync方法将会测试验证从API获取所有专辑的调用。就像之前讨论的单元测试一样,集成测试的逻辑也是用了Arrange、Act和Assert。我们首先创建HttpRequestMessage对象,其中HTTP作为InlineData注释中的变量而提供,URI部分表示对于所有的专辑的调用(“/api/Album/”)。之后我们会让HttpClient _client发送HTTP请求,最后,我们会检查验证HTTP响应是否满足我们的期望,在本例中是200。图4中我展示了两种检验API调用的方法。你可以使用其中任意一种,但我更喜欢第二种方法,因为它允许我用相同的模式来检验对特定HTTP响应代码的响应。
response.EnsureSuccessStatusCode();Assert.Equal(HttpStatusCode.OK, response.StatusCode);
我们还可以创建需要从API测试特定实体键的集成测试。对于这类测试,我们需要在InlineData注释中添加额外的值,将会通过AlbumGetTestAsync方法参数传递。我们的新测试会使用相同的逻辑,并使用和之前测试一样的资源,但是我们为HttpRequestMessage对象在API URI端中传递实体键。你可以在图5中查看代码。
图5:专辑的第二个集成测试
在你为测试API创造了所有集成测试之后,需要通过Test Runner来运行它们,并保证它们全部通过。你创建的所有测试也可以在DevOps持续集成(CI)过程中执行,这样可以在整体开发和部署过程中测试你的API。现在需要有执行路径保证你的API在开发、质量保证和部署阶段都得到测试和维护,让你的API使用者拥有良好体验的同时不发生意外情况。
图6:在Visual Studio 2017中运行集成测试
拥有良好设计的一套测试计划,使用单元测试来做内部测试,使用集成测试来验证API调用就和开发ASP .NET Core Web API阶段创建架构是一样重要的。
Chris Woodruff (Woody) 拥有密歇根州立大学工程学院的计算机科学学位。Woody 已经开发和架构软件解决方案超过 20 年,并且曾经致力于许多不同的平台和工具。他是一个社区领袖,为 GRDevNight、GRDevDay、West Michigan Day of .NET 和 CodeMash 之类的活动贡献过力量。他还帮助把广受欢迎的 Give Camp 活动带到西密歇根,那里的技术专业人士提供他们的时间和发展专业知识,以帮助当地的非营利组织。作为一个演讲者和播客作者,Woody 演讲和讨论过很多话题,包括数据库设计和开源。他在 Visual C#、数据平台和 SQL 方面一直是微软的 MVP,并在 2010 年被公认为全球最优秀的 20 个 MVPs 之一。Woody 是 JetBrains 的开发者,并且在北美推广 .NET、.NET Core 和 JetBrains 的产品。
.NET Core 最初是在 2016 年发布的,随着 .NET Core 2.0 的发布,微软拥有了下一个通用、模块化、跨平台和开源的平台主版本。.NETCore 已经创建了许多 API,在当前版本的 .net 框架中均可用。它最初是为下一代 ASP .NET解决方案而创建的,但现在成了许多其他场景的驱动和基础,包括物联网、云计算和下一代移动解决方案。在本系列文章中,我们将探讨 .NET Core 的一些好处,以及它如何不仅能使传统的 .NET 开发人员受益,还能使所有需要为市场带来健壮、高效和经济的解决方案的技术人员受益。
InfoQ 的这篇文章是“”这个系列的一部分。您可以通过 RSS 订阅接收通知。
查看英文原文:
转载地址:http://btsfx.baihongyu.com/