使用 dotnet test 和 xUnit 在 .NET Core 中进行 C# 单元测试Unit testing C# in .NET Core using dotnet test and xUnit

本文内容

本教程介绍分步构建示例解决方案的交互式体验,以了解单元测试概念。如果希望使用预构建解决方案学习本教程,请在开始前查看或下载示例代码有关下载说明,请参阅示例和教程

本文介绍如何测试 .NET Core 项目。如果要测试 ASP.NET Core 项目,请参阅 ASP.NET Core 中的集成测试

创建源项目Creating the source project

打开 shell 窗口。创建一个名为 unit-testing-using-dotnet-test 的目录,以保留该解决方案。在此新目录中,运行 dotnet new sln 创建新的解决方案。通过解决方案,可轻松管理类库和单元测试项目。在解决方案目录中,创建 PrimeService 目录。现在,目录和文件结构应如下所示:

  1. /unit-testing-using-dotnet-test
  2. unit-testing-using-dotnet-test.sln
  3. /PrimeService

PrimeService 作为当前目录,然后运行 dotnet new classlib 以创建源项目。Class1.cs 重命名为 PrimeService.cs首先创建 PrimeService 类的失败实现:

  1. using System;
  2. namespace Prime.Services
  3. {
  4. public class PrimeService
  5. {
  6. public bool IsPrime(int candidate)
  7. {
  8. throw new NotImplementedException("Please create a test first.");
  9. }
  10. }
  11. }

将目录更改回 unit-testing-using-dotnet-test 目录。

运行 dotnet sln 命令,向解决方案添加类库项目:

  1. dotnet sln add ./PrimeService/PrimeService.csproj

创建测试项目Creating the test project

接下来,创建 PrimeService.Tests 目录。下图显示了它的目录结构:

  1. /unit-testing-using-dotnet-test
  2. unit-testing-using-dotnet-test.sln
  3. /PrimeService
  4. Source Files
  5. PrimeService.csproj
  6. /PrimeService.Tests

PrimeService.Tests 目录作为当前目录,并使用 dotnet new xunit 创建一个新项目。此命令会创建将 xUnit 用作测试库的测试项目。生成的模板在 PrimeServiceTests.csproj 文件中配置测试运行程序,类似以下代码 :

  1. <ItemGroup>
  2. <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
  3. <PackageReference Include="xunit" Version="2.2.0" />
  4. <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
  5. </ItemGroup>

测试项目需要其他包创建和运行单元测试。dotnet new 在以前的步骤中已添加 xUnit 和 xUnit 运行程序。现在,将 PrimeService 类库作为另一个依赖项添加到项目中。使用 dotnet add reference 命令:

  1. dotnet add reference ../PrimeService/PrimeService.csproj

可以在 GitHub 上的示例存储库中看到整个文件。

下面显示的是最终的解决方案布局:

  1. /unit-testing-using-dotnet-test
  2. unit-testing-using-dotnet-test.sln
  3. /PrimeService
  4. Source Files
  5. PrimeService.csproj
  6. /PrimeService.Tests
  7. Test Source Files
  8. PrimeServiceTests.csproj

若要向解决方案添加测试项目,请在 unit-testing-using-dotnet-test 目录下运行 dotnet sln 命令 :

  1. dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

创建第一个测试Creating the first test

编写一个失败测试,使其通过,然后重复此过程。从 PrimeService.Tests 目录删除 UnitTest1.cs ,并创建一个名为 PrimeService_IsPrimeShould.cs 的新 C# 文件。添加以下代码:

  1. using Xunit;
  2. using Prime.Services;
  3. namespace Prime.UnitTests.Services
  4. {
  5. public class PrimeService_IsPrimeShould
  6. {
  7. private readonly PrimeService _primeService;
  8. public PrimeService_IsPrimeShould()
  9. {
  10. _primeService = new PrimeService();
  11. }
  12. [Fact]
  13. public void IsPrime_InputIs1_ReturnFalse()
  14. {
  15. var result = _primeService.IsPrime(1);
  16. Assert.False(result, "1 should not be prime");
  17. }
  18. }
  19. }

[Fact] 属性指示由测试运行程序运行的测试方法。在 PrimeService.Tests 文件夹中,执行 dotnet test,以生成测试和类库,然后运行测试 。xUnit 测试运行程序包含要运行测试的程序入口点。dotnet test 使用已创建的单元测试项目启动测试运行程序。

测试失败。尚未创建实现。在起作用的 PrimeService 类中编写最简单的代码,使此测试通过。将现有的 IsPrime 方法实现替换为以下代码:

  1. public bool IsPrime(int candidate)
  2. {
  3. if (candidate == 1)
  4. {
  5. return false;
  6. }
  7. throw new NotImplementedException("Please create a test first.");
  8. }

PrimeService.Tests 目录中,再次运行 dotnet testdotnet test 命令构建 PrimeService 项目,然后构建 PrimeService.Tests 项目。构建这两个项目后,该命令将运行此单项测试。测试通过。

添加更多功能Adding more features

你已经通过了一个测试,现在可以编写更多测试。质数有其他几种简单情况:0、-1。可以将这些情况添加为具有 [Fact] 属性的新测试,但这很快就会变得枯燥乏味。还有其他 xUnit 属性,可使你编写类似测试套件:

  • [Theory] 表示执行相同代码,但具有不同输入参数的测试套件。

  • [InlineData] 属性指定这些输入的值。

可应用这两个属性([Theory][InlineData])在 PrimeService_IsPrimeShould.cs 文件中创建单一理论,而不是创建新测试 。此索引是测试多个小于 2(即最小的质数)的值的方法:

  1. [Theory]
  2. [InlineData(-1)]
  3. [InlineData(0)]
  4. [InlineData(1)]
  5. public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
  6. {
  7. var result = _primeService.IsPrime(value);
  8. Assert.False(result, $"{value} should not be prime");
  9. }

再次运行 dotnet test,其中两个测试应失败。若要使所有测试通过,可以在 PrimeService.cs 文件中更改 IsPrime 方法开头的 if 子句 :

  1. if (candidate < 2)

通过在主库中添加更多测试、理论和代码继续循环访问。你将拥有已完成的测试版本库的完整实现

其他资源Additional resources