新建xUnit测试项目必须用dotnet new xunit,确保含Microsoft.NET.Test.Sdk和xunit依赖;测试类需public无参构造,方法为public void或带Timeout的async Task;NUnit测试方法必须返回void(async需NUnit3.8+及适配器);测internal需在被测项目加,private需反射调用但不推荐;dotnet test失败多因缺Microsoft.NET.Test.Sdk、适配器未安装或异步/超时配置不当。

怎么在 C# 项目里快速跑起第一个 xUnit 测试
直接加包、写类、用 [Fact] 标记方法,就能跑。但很多人卡在「测试项目没识别出来」或「dotnet test 找不到测试」——根本原因是项目类型和 SDK 不匹配。
- 新建测试项目必须用
dotnet new xunit(不是console或classlib),它会自动配置Microsoft.NET.Test.Sdk和xunit依赖 - 确保测试类是
public,且不带构造函数参数(xUnit 不支持带参构造注入到测试类) - 测试方法必须是
public void(不能是async Task除非用[Fact(Timeout = 1000)]并显式 await) - 别手动改
.csproj里的,xUnit 3.0+ 要求 .NET 6+,混用 .NET Framework 会静默跳过测试
NUnit 测试为什么总提示“Method has non-void return type”
这是最常被忽略的语法陷阱:NUnit 要求所有测试方法返回 void,连 Task 都不行(和 xUnit 不同)。哪怕你写了 async Task,NUnit 2.x/3.x 默认不识别,直接报这个错。
- 正确写法是
public async Task MyTest()+[Test],但必须同时引用NUnit3TestAdapter(VS 识别用)和启用异步支持(NUnit 3.8+ 默认开启) - 更稳妥的做法是用
public void MyTest()+Assert.That(asyncMethod().Result, Is.EqualTo(...)),避免适配器兼容问题 - 如果用的是 NUnit 2.x,压根不支持 async,必须降级为同步调用或升级
- 注意
[SetUp]和[TearDown]方法也必须是void,不能是 async
测试私有方法或 internal 类型要开什么开关
默认跑不通。C# 单元测试项目和被测项目是两个独立程序集,internal 成员不可见,private 更不可能反射调用——除非你主动打开门。
- 在被测项目的
.csproj中添加:(注意名字要和测试项目的YourTestProjectName AssemblyName一致,不是文件名) - 测试项目里不能直接访问 private 方法;想测,得用
typeof(TargetClass).GetMethod("MethodName", BindingFlags.NonPublic | BindingFlags.Instance)+Invoke(),但容易因重载、参数类型错位崩溃 - 真正该做的,是测 public 行为覆盖 private 路径,而不是强行打洞。90% 的“必须测 private”其实是设计信号:这个逻辑该抽成 public service 或用 protected virtual 给测试 mock
- 如果用了强名称签名(
snk),InternalsVisibleTo还得带上公钥,否则无效
dotnet test 命令找不到测试或超时失败
不是代码问题,大概率是环境或配置链断了。xUnit/NUnit 都依赖测试运行器适配器,而 dotnet test 只认 Microsoft.NET.Test.Sdk 这个统一入口。
- 检查测试项目是否真的包含
—— 缺这个,dotnet test直接当普通库跳过 - VS Code 用户容易漏装
C# Dev Kit或禁用dotnet-test-explorer插件,导致 GUI 点运行没反应 - 超时常见于测试里用了
Thread.Sleep或未 await 的异步 IO(比如忘了HttpClient调用后的await),实际卡在等待上 - Linux/macOS 下若用
dotnet test --filter,注意通配符语法是FullName~MyNamespace,不是*,写错就过滤为空
测试框架本身不难,难的是每一步都依赖正确的 assembly visibility、SDK 版本对齐、以及不把测试当成黑盒来猜——尤其是 internal 和 async 这两块,稍不留神就变成“能编译,但不执行”。










