本教程逐步讲解了构建示例解决方案的交互式体验,以学习单元测试概念。
本文介绍如何测试 .NET Core 项目。 如果要测试 ASP.NET Core 项目,请参阅 ASP.NET Core中的
Prerequisites
- .NET 10 SDK 或更高版本。
- 你选择的文本编辑器或代码编辑器。
TUnit 完全基于 Microsoft.Testing.Platform (MTP),不支持 VSTest。 本教程使用 dotnet test 的 MTP 模式,该模式需要 .NET 10 SDK。
创建源项目
打开 shell 窗口。 创建名为 unit-testing-using-tunit 的目录来存放该解决方案。 在此新目录中,运行以下命令,为类库和测试项目创建新的解决方案文件:
dotnet new sln
接下来,创建 PrimeService 目录。 以下大纲显示到目前为止的目录和文件结构:
/unit-testing-using-tunit
unit-testing-using-tunit.slnx
/PrimeService
将 PrimeService 设为当前目录并运行以下命令以创建源项目:
dotnet new classlib
将 Class1.cs 重命名为 PrimeService.cs。 创建 PrimeService 类的失败实现:
using System;
namespace Prime.Services
{
public class PrimeService
{
public bool IsPrime(int candidate)
{
throw new NotImplementedException("Please create a test first.");
}
}
}
将目录更改回 unit-testing-using-tunit 目录。 运行以下命令,将类库项目添加到解决方案:
dotnet sln add PrimeService/PrimeService.csproj
创建测试项目
接下来,创建 PrimeService.Tests 目录。 以下大纲显示了目录结构:
/unit-testing-using-tunit
unit-testing-using-tunit.slnx
/PrimeService
Source Files
PrimeService.csproj
/PrimeService.Tests
.NET SDK 中不包含 TUnit 项目模板。 使用以下命令安装它们:
dotnet new install TUnit.Templates
将目录更改为 PrimeService.Tests 目录,并使用以下命令创建新项目:
dotnet new TUnit
Note
模板短名称区分大小写。 使用 TUnit,而不是 tunit。
dotnet new 命令创建一个使用 TUnit 作为测试库的测试项目。 生成的 PrimeService.Tests.csproj 文件是引用 TUnit 包的可执行项目(版本号可能有所不同):
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" Version="1.*" />
</ItemGroup>
该 TUnit 包包括测试框架、断言库和 MTP 测试运行程序,因此项目不需要任何其他测试包。 该模板还会添加示例测试。 从 PrimeService.Tests 目录中删除所有 .cs 文件和 Data 目录,因为本教程将用自己的测试替换它们。
现在,将 PrimeService 类库添加为项目的另一个依赖项。 使用 dotnet reference add 命令:
dotnet reference add ../PrimeService/PrimeService.csproj
以下大纲显示了最终解决方案布局:
/unit-testing-using-tunit
unit-testing-using-tunit.slnx
/PrimeService
Source Files
PrimeService.csproj
/PrimeService.Tests
Test Source Files
PrimeService.Tests.csproj
在 unit-testing-using-tunit 目录中执行以下命令:
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
配置 dotnet 测试的 MTP 模式
由于 TUnit 不支持 VSTest, dotnet test 因此必须在其 MTP 模式下运行。 在 unit-testing-using-tunit 目录中,创建包含以下内容的 global.json 文件:
{
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
有关详细信息,请参阅 dotnet 测试的 MTP 模式。
创建第一个测试
编写一个失败的测试,使其通过,然后重复该过程。 在 PrimeService.Tests 目录中,使用以下代码创建 PrimeService_IsPrimeShould.cs 文件:
namespace Prime.UnitTests.Services
{
using Prime.Services;
public class PrimeService_IsPrimeShould
{
private readonly PrimeService _primeService = new();
[Test]
public async Task IsPrime_InputIs1_ReturnFalse()
{
var result = _primeService.IsPrime(1);
await Assert.That(result).IsFalse();
}
}
}
该 [Test] 属性指示方法是测试方法。 TUnit 不需要在类上添加特性。 TUnit 断言是异步的,因此测试方法返回 Task 并等待 Assert.That。 该 TUnit 包为其命名空间添加全局 using 指令,因此该文件不需要它们。
Note
指令 using Prime.Services; 是有意放在命名空间内的。 MTP 在项目的根命名空间 PrimeService.Tests中生成测试应用程序的入口点。 该命名空间会将 using 类对文件顶部的 PrimeService 指令隐藏,但不会对命名空间内的指令隐藏该类。
保存此文件并执行 dotnet test 命令以生成测试和类库并运行测试。 TUnit 测试项目包含用于运行测试的程序入口点。
dotnet test 使用已创建的单元测试项目启动测试运行程序。
测试失败。 你还没有创建实现。 通过在可工作的类中 PrimeService 编写最简单的代码,使测试通过:
public bool IsPrime(int candidate)
{
if (candidate == 1)
{
return false;
}
throw new NotImplementedException("Please create a test first.");
}
在 unit-testing-using-tunit 目录中,再次运行 dotnet test 。
dotnet test 命令构建 PrimeService 项目,然后构建 PrimeService.Tests 项目。 生成这两个项目后,它将运行此单一测试。 测试通过。
添加更多功能
你已经通过了一个测试,现在可以编写更多测试。 质数有其他几种简单情况:0,-1。 可以添加新测试,使用[Test]属性,但这很快变得繁琐。 TUnit 提供 [Arguments] 属性,用于创建执行相同代码但具有不同输入参数的测试套件。
不要创建新测试,而是应用此属性来创建单个数据驱动测试。 使用以下代码替换 IsPrime_InputIs1_ReturnFalse 方法。 数据驱动测试是一种测试小于 2 的多个值的方法,这是最低质数:
[Test]
[Arguments(-1)]
[Arguments(0)]
[Arguments(1)]
public async Task IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
var result = _primeService.IsPrime(value);
await Assert.That(result).IsFalse();
}
运行 dotnet test,两项测试均失败。 若要使所有测试通过,可以在 PrimeService.cs 文件中更改 if 方法开头的 IsPrime 子句:
if (candidate < 2)
通过在主库中添加更多测试和代码,继续迭代。
你为该库构建了一个小库和一组单元测试。 你还构建了解决方案,以便添加新的包和测试是标准工作流的一部分。 你大部分时间都专注于解决应用程序的目标。