添加.NET测试基础设施 dotnet-add-testing

这个技能用于在现有.NET项目中添加完整的测试基础设施,包括创建xUnit测试项目、配置coverlet代码覆盖、设置目录结构,以支持单元测试和集成测试。关键词:.NET, 测试, xUnit, coverlet, 代码覆盖, 项目结构, 单元测试, 集成测试, 测试脚手架, DevOps。

测试 0 次安装 0 次浏览 更新于 3/6/2026

name: dotnet-add-testing description: “向.NET项目添加测试基础设施。搭建xUnit项目、coverlet、布局。”

dotnet-add-testing

向现有.NET项目添加测试基础设施脚手架。创建包含xUnit的测试项目,配置coverlet代码覆盖,并设置常规目录结构。

范围

  • 使用xUnit和coverlet创建测试项目
  • 常规目录结构(tests/镜像src/)
  • 项目引用连接和测试SDK配置

超出范围

  • 深入的测试模式(xUnit v3、WebApplicationFactory、UI测试)——参见[skill:dotnet-testing-strategy]

先决条件: 首先运行[skill:dotnet-version-detection]以确定SDK版本和TFM。运行[skill:dotnet-project-analysis]以了解现有解决方案结构。

交叉引用:[skill:dotnet-project-structure]用于整体解决方案布局惯例,[skill:dotnet-scaffold-project]包括新项目中的测试脚手架,[skill:dotnet-add-analyzers]用于测试特定分析器抑制。


测试项目结构

遵循镜像src/项目名称到tests/下的惯例:

MyApp/
├── src/
│   ├── MyApp.Core/
│   ├── MyApp.Api/
│   └── MyApp.Infrastructure/
└── tests/
    ├── MyApp.Core.UnitTests/
    ├── MyApp.Api.UnitTests/
    ├── MyApp.Api.IntegrationTests/
    └── Directory.Build.props          # 测试特定构建设置

命名惯例:

  • *.UnitTests —— 无外部依赖的隔离测试
  • *.IntegrationTests —— 使用真实基础设施(数据库、HTTP、文件系统)的测试
  • *.FunctionalTests —— 通过完整应用程序堆栈的端到端测试

步骤1:创建测试项目

# 创建xUnit测试项目
dotnet new xunit -n MyApp.Core.UnitTests -o tests/MyApp.Core.UnitTests

# 添加到解决方案
dotnet sln add tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj

# 添加对被测项目的引用
dotnet add tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj \
  reference src/MyApp.Core/MyApp.Core.csproj

清理生成的项目

移除已在Directory.Build.props中定义的属性:

<!-- tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" />
    <PackageReference Include="xunit.v3" />
    <PackageReference Include="xunit.runner.visualstudio" />
    <PackageReference Include="coverlet.collector" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\src\MyApp.Core\MyApp.Core.csproj" />
  </ItemGroup>
</Project>

使用CPM时,Version属性在Directory.Packages.props中管理。从生成的.csproj中移除它们。


步骤2:添加测试特定构建属性

创建tests/Directory.Build.props以自定义所有测试项目的设置:

<!-- tests/Directory.Build.props -->
<Project>
  <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
  <PropertyGroup>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
    <!-- 使用Microsoft.Testing.Platform v2运行器(需要Microsoft.NET.Test.Sdk 17.13+/18.x) -->
    <UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
    <!-- 为测试项目放宽严格性 -->
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
  </PropertyGroup>
</Project>

这导入根Directory.Build.props(用于共享设置如NullableImplicitUsingsLangVersion)并覆盖测试特定属性。


步骤3:在CPM中注册测试包

Directory.Packages.props添加测试包版本:

<!-- 在Directory.Packages.props中 -->
<ItemGroup>
  <!-- 测试包 -->
  <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
  <PackageVersion Include="xunit.v3" Version="3.2.2" />
  <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
  <PackageVersion Include="coverlet.collector" Version="8.0.0" />
</ItemGroup>

可选:模拟库

如果项目需要测试替身,添加模拟库:

<PackageVersion Include="NSubstitute" Version="5.3.0" />

或用于断言库:

<PackageVersion Include="FluentAssertions" Version="8.0.1" />

步骤4:配置代码覆盖

Coverlet(收集器模式)

coverlet.collector包通过数据收集器与dotnet test集成。基本覆盖无需额外配置。

生成覆盖报告:

# 收集覆盖(默认Cobertura格式)
dotnet test --collect:"XPlat Code Coverage"

# 结果出现在TestResults/*/coverage.cobertura.xml中

覆盖阈值

对于CI强制执行,使用coverlet.msbuild进行阈值检查:

<!-- 在测试csproj或tests/Directory.Build.props中 -->
<PackageReference Include="coverlet.msbuild" />
# 强制执行最小覆盖阈值
dotnet test /p:CollectCoverage=true \
  /p:CoverageOutputFormat=cobertura \
  /p:Threshold=80 \
  /p:ThresholdType=line

覆盖报告生成

使用reportgenerator生成人类可读的HTML报告:

# 全局安装
dotnet tool install -g dotnet-reportgenerator-globaltool

# 生成HTML报告
reportgenerator \
  -reports:"tests/**/coverage.cobertura.xml" \
  -targetdir:coverage-report \
  -reporttypes:Html

步骤5:为测试添加EditorConfig覆盖

在根.editorconfig中,添加测试特定放宽:

[tests/**.cs]
# 允许测试方法名中的下划线(Given_When_Then或Should_Behavior)
dotnet_diagnostic.CA1707.severity = none

# 测试参数由框架验证
dotnet_diagnostic.CA1062.severity = none

# ConfigureAwait在测试上下文中不相关
dotnet_diagnostic.CA2007.severity = none

# 测试中常有意未使用的变量用于断言
dotnet_diagnostic.IDE0059.severity = suggestion

步骤6:编写起始测试

替换模板生成的UnitTest1.cs为适当结构的测试:

namespace MyApp.Core.UnitTests;

public class SampleServiceTests
{
    [Fact]
    public void Method_Condition_ExpectedResult()
    {
        // 安排
        var sut = new SampleService();

        // 行动
        var result = sut.DoWork();

        // 断言
        Assert.NotNull(result);
    }

    [Theory]
    [InlineData(1, 2, 3)]
    [InlineData(0, 0, 0)]
    [InlineData(-1, 1, 0)]
    public void Add_TwoNumbers_ReturnsSum(int a, int b, int expected)
    {
        var result = Calculator.Add(a, b);
        Assert.Equal(expected, result);
    }
}

测试命名惯例

使用模式Method_Condition_ExpectedResult

  • CreateUser_WithValidInput_ReturnsUser
  • GetById_WhenNotFound_ReturnsNull
  • Delete_WithoutPermission_ThrowsUnauthorized

验证

添加测试基础设施后,验证一切工作:

# 恢复(如果使用CPM,重新生成锁定文件)
dotnet restore

# 构建(验证项目引用和分析器配置)
dotnet build --no-restore

# 运行测试
dotnet test --no-build

# 运行覆盖
dotnet test --collect:"XPlat Code Coverage"

添加集成测试项目

对于需要WebApplicationFactory或数据库访问的集成测试:

dotnet new xunit -n MyApp.Api.IntegrationTests -o tests/MyApp.Api.IntegrationTests
dotnet sln add tests/MyApp.Api.IntegrationTests/MyApp.Api.IntegrationTests.csproj
dotnet add tests/MyApp.Api.IntegrationTests/MyApp.Api.IntegrationTests.csproj \
  reference src/MyApp.Api/MyApp.Api.csproj

向CPM添加集成测试包(匹配Microsoft.AspNetCore.Mvc.Testing的主版本到目标框架——例如,net8.08.xnet9.09.xnet10.010.x):

<!-- 版本必须匹配项目的目标框架主版本 -->
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
<PackageVersion Include="Testcontainers" Version="4.3.0" />

集成测试深度(WebApplicationFactory模式、测试容器、数据库夹具)——参见[skill:dotnet-integration-testing]。


下一步

本技能涵盖测试项目脚手架。更深测试指南:

  • xUnit v3特性和模式 —— [skill:dotnet-xunit]
  • 使用WebApplicationFactory进行集成测试 —— [skill:dotnet-integration-testing]
  • UI测试(Blazor、MAUI、Uno) —— [skill:dotnet-blazor-testing], [skill:dotnet-maui-testing], [skill:dotnet-uno-testing]
  • 快照测试 —— [skill:dotnet-snapshot-testing]
  • 测试质量和覆盖强制执行 —— [skill:dotnet-test-quality]
  • CI测试报告 —— [skill:dotnet-add-ci]用于起始,[skill:dotnet-gha-build-test]和[skill:dotnet-ado-build-test]用于高级

参考文献