C#单元测试(一):用 NUnit 和 .NET Core 进行单元测试

本教程通过一步步构建示例解决方案,为您提供一个互动体验,帮助您学习单元测试的概念。如果您更愿意使用预先构建的解决方案来学习本教程,可以在开始之前查看或下载示例代码

创建源项目

打开一个终端窗口。创建一个名为“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 testdotnet 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 CopilotChatGPT Plus (半价开通,无需账号即可使用)简直不要太香。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值