本教程通过一步步构建示例解决方案,为您提供一个互动体验,帮助您学习单元测试的概念。如果您更愿意使用预先构建的解决方案来学习本教程,可以在开始之前查看或下载示例代码。
创建源项目
打开一个终端窗口。创建一个名为“unit-testing-using-nunit”的目录来存放解决方案。在这个新目录中,运行以下命令来为类库和测试项目创建一个新的解决方案文件:
dotnet new sln
下一步,创建 PrimeService
目录。下面展示了当前的目录结构:
/unit-testing-using-nunit
unit-testing-using-nunit.sln
/PrimeService
进入 PrimeService
目录,然后运行下面的命令创建源项目:
dotnet new classlib
将文件名 Class1.cs
重命名为 PrimeService.cs
。然后,该文件的代码如下:
using System;
namespace Prime.Services
{
public class PrimeService
{
public bool IsPrime(int candidate)
{
throw new NotImplementedException("Please create a test first.");
}
}
}
这是一个失败的测试用例,因为函数 IsPrime
直接抛出了异常。这符合测试驱动开发的原则:红-绿-重构。红,即编写一个失败的测试用例,绿,即实现正确的功能,使测试通过。重构,修改正确的代码。
将目录切换到 unit-testing-using-nunit
目录。 运行以下命令,向解决方案添加类库项目:
dotnet sln add PrimeService/PrimeService.csproj
1. 创建测试项目
接下来,创建 PrimeService.Tests
目录。 下图显示了它的目录结构:
/unit-testing-using-nunit
unit-testing-using-nunit.sln
/PrimeService
Source Files
PrimeService.csproj
/PrimeService.Tests
将 PrimeService.Tests
目录作为当前目录,并使用以下命令创建一个新项目:
dotnet new nunit
dotnet new
命令可创建一个将 NUnit 用作测试库的测试项目。 生成的模板在 PrimeService.Tests.csproj
,该文件的内容:
<ItemGroup>
<PackageReference Include="nunit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
在 .NET 9 之前,生成的代码可能会引用较旧版本的 NUnit 测试框架。 可以使用 dotnet CLI 更新包。 或者,打开 PrimeService.Tests.csproj 文件,用上面的代码替换包引用项组的内容。
测试项目需要创建其它包和运行单元测试。 在上一步中,dotnet new
命令已添加 Microsoft 测试 SDK、NUnit 测试框架和 NUnit 测试适配器。 由于 PrimeService.Test
项目使用 PrimeService
类库。所以需要将 PrimeService
类库作为另一个依赖项添加到项目中。 在 PrimeService.Tests
目录下使用 dotnet add reference
命令:
dotnet add reference ../PrimeService/PrimeService.csproj
下图显示了最终的解决方案目录结构:
/unit-testing-using-nunit
unit-testing-using-nunit.sln
/PrimeService
Source Files
PrimeService.csproj
/PrimeService.Tests
Test Source Files
PrimeService.Tests.csproj
在 unit-testing-using-nunit
目录中执行以下命令:
.NET CLI
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
2. 创建第一个测试
编写一个失败测试,使其通过,然后重复此过程。 在 PrimeService.Tests
目录中,将 UnitTest1.cs
文件重命名为 PrimeService_IsPrimeShould.cs
,并将其整个内容替换为以下代码:
using NUnit.Framework;
using Prime.Services;
namespace Prime.UnitTests.Services
{
[TestFixture]
public class PrimeService_IsPrimeShould
{
private PrimeService _primeService;
[SetUp]
public void SetUp()
{
_primeService = new PrimeService();
}
[Test]
public void IsPrime_InputIs1_ReturnFalse()
{
var result = _primeService.IsPrime(1);
Assert.That(result, Is.False, "1 should not be prime");
}
}
}
代码解释:
[TestFixture]
属性该类是一个测试类;[SetUp]
属性用于标记在每个测试方法运行之前需要执行的代码;[Test]
属性表明该方法是一个测试方法。
保存此文件并执行 dotnet test
命令以构建测试和类库,然后运行测试。 NUnit 测试运行程序包含要运行测试的程序入口点。 dotnet test
使用已创建的单元测试项目启动测试运行程序。
测试失败了,因为被测试的函数直接抛出了一个异常:
在 PrimeService 类中编写最简单的代码,使此测试通过:
public bool IsPrime(int candidate)
{
if (candidate == 1)
{
return false;
}
throw new NotImplementedException("Please create a test first.");
}
在 unit-testing-using-nunit
目录中再次运行 dotnet test
。 dotnet test
命令构建 PrimeService
项目,然后构建 PrimeService.Tests
项目。 构建这两个项目后,该命令将运行此单项测试。
3. 添加更多的测试
小于 2 的正整数都不是质数,我们可以分别为 0、1 编写单独的测试用例,但这很枯燥。[TestCase]
属性用于创建一套可执行相同代码但具有不同输入参数的测试。
例如,我们增加以下测试代码:
// 使用 TestCase 为测试方法提供多组测试数据
[TestCase(-1, false)]
[TestCase(0, false)]
[TestCase(1, false)]
[TestCase(2, true)]
[TestCase(3, true)]
[TestCase(4, false)]
public void IsPrime_TestVariousInputs(int input, bool expectedResult)
{
var result = _primeService.IsPrime(input);
Assert.That(result, Is.EqualTo(expectedResult), $"{input} should return {expectedResult}");
}
这实际上包含了 6 个测试用例。再次运行测试:
小结:本节我们生成了一个小型库和该库的一组单元测试。
最后,给各位道友介绍一下使用国外虚拟卡开通一些国外服务的渠道,当前我在用的是 wildcard,使用我的注册邀请码 IOQ1YDHH
注册,你能得 2 美刀,可用来抵消一部分的开卡费用。自己买个 Github Copilot
、ChatGPT Plus
(半价开通,无需账号即可使用)简直不要太香。