c# 如何进行单元测试

来源:这里教程网 时间:2026-02-21 17:38:05 作者:

dotnet test
运行测试前必须装什么

不装测试运行器,

dotnet test
会报错
Could not find a test host executable
。核心是三样东西缺一不可:

Microsoft.NET.Test.Sdk
:提供测试宿主和基础框架
一个测试框架包,比如
xunit
nunit
mstest
对应框架的运行器,例如
xunit.runner.visualstudio
(用于 VS 和
dotnet test

推荐直接用

xunit
,它和 .NET SDK 集成最稳。添加方式:
dotnet add package xunit<br>dotnet add package xunit.runner.visualstudio<br>dotnet add package Microsoft.NET.Test.Sdk
注意:.NET 6+ 项目中,
Microsoft.NET.Test.Sdk
是必需的,否则
dotnet test
根本识别不出测试项目。

[Fact]
[Theory]
怎么选

[Fact]
用于无参数、固定逻辑的单次验证;
[Theory]
必须配合
[InlineData]
[MemberData]
等数据源,适合验证同一逻辑在多组输入下的行为。

常见误用是把本该用

[Theory]
的边界测试硬写成多个
[Fact]
,既冗余又难维护。比如验证字符串长度限制:

public class StringValidatorTests<br>{<br>    [Theory]<br>    [InlineData("a", true)]<br>    [InlineData("ab", true)]<br>    [InlineData("abc", false)] // 超长<br>    public void ValidateLength_WithVariousInputs_ReturnsExpected(string input, bool expected)<br>    {<br>        var result = StringValidator.ValidateLength(input, maxLength: 2);<br>        Assert.Equal(expected, result);<br>    }<br>}

如果只测一种情况,用

[Fact]
更直白;但凡涉及输入组合、边界值、空/零/负数等,优先上
[Theory]

如何让测试访问
internal
成员

被测类或方法设为

internal
是常见做法,但默认情况下测试项目无法访问。解决方法是在被测项目的
.csproj
中加一行:
<ItemGroup><br>  <InternalsVisibleTo Include="MyApp.Tests" /><br></ItemGroup>
其中
MyApp.Tests
是测试项目的程序集名(不是文件夹名,也不是命名空间)。如果测试项目启用了强名称签名,还得补上公钥:
<InternalsVisibleTo Include="MyApp.Tests, PublicKey=00240000048000009400000006020000..." />
漏掉这步,编译不报错,但运行时
Assert
会失败——因为根本调不到目标方法,
null
或默认值导致断言崩了,容易误判为逻辑错误。

异步方法测试必须用
async Task
当返回类型

async void
或忽略
await
是最常踩的坑。以下写法会导致测试“假通过”:
[Fact]<br>public void WhenCallingApi_ThenReturnsData() // ❌ 返回 void<br>{<br>    var result = await MyService.GetDataAsync(); // 编译不过,但假设你绕过了<br>    Assert.NotNull(result);<br>}
正确写法必须是:
[Fact]<br>public async Task WhenCallingApi_ThenReturnsData() // ✅<br>{<br>    var result = await MyService.GetDataAsync();<br>    Assert.NotNull(result);<br>}
原因:xUnit 需要控制异步生命周期,只有返回
Task
才能真正等待完成。否则测试框架在异步操作结束前就标记为通过,掩盖真实问题。

测试里最容易被忽略的是异步等待的完整性,以及

internal
成员的可见性配置——这两处不显式处理,问题往往延迟暴露,查起来反而更费时间。

相关推荐