SKILL.md
readonly只读
name
csharp-xunit
description
获取 XUnit 单元测试的最佳实践,包括数据驱动测试
XUnit 最佳实践
您的目标是帮助我使用 XUnit 编写有效的单元测试,涵盖标准测试和数据驱动测试方法。
项目设置
- 使用单独的测试项目,命名约定为
[ProjectName].Tests - 引用 Microsoft.NET.Test.Sdk、xunit 和 xunit.runner.visualstudio 包
- 创建与被测试类匹配的测试类(例如,
CalculatorTests对应Calculator) - 使用 .NET SDK 测试命令:
dotnet test运行测试
测试结构
- 不需要测试类属性(与 MSTest/NUnit 不同)
- 对于简单测试,使用带有
[Fact]属性的基于事实的测试 - 遵循 Arrange-Act-Assert (AAA) 模式
- 使用
MethodName_Scenario_ExpectedBehavior模式命名测试 - 使用构造函数进行设置,使用
IDisposable.Dispose()进行清理 - 使用
IClassFixture<T>在类中的测试之间共享上下文 - 使用
ICollectionFixture<T>在多个测试类之间共享上下文
标准测试
- 保持测试专注于单一行为
- 避免在一个测试方法中测试多个行为
- 使用清晰的断言来表达意图
- 仅包含验证测试用例所需的断言
- 使测试独立且幂等(可以按任意顺序运行)
- 避免测试之间的相互依赖
数据驱动测试
- 使用
[Theory]结合数据源属性 - 使用
[InlineData]提供内联测试数据 - 使用
[MemberData]提供基于方法的测试数据 - 使用
[ClassData]提供基于类的测试数据 - 通过实现
DataAttribute创建自定义数据属性 - 在数据驱动测试中使用有意义的参数名称
断言
- 使用
Assert.Equal进行值相等性比较 - 使用
Assert.Same进行引用相等性比较 - 使用
Assert.True/Assert.False进行布尔条件判断 - 使用
Assert.Contains/Assert.DoesNotContain进行集合检查 - 使用
Assert.Matches/Assert.DoesNotMatch进行正则表达式模式匹配 - 使用
Assert.Throws<T>或await Assert.ThrowsAsync<T>测试异常 - 使用流畅断言库以获得更可读的断言
模拟和隔离
- 考虑将 Moq 或 NSubstitute 与 XUnit 一起使用
- 模拟依赖项以隔离被测单元
- 使用接口以方便模拟
- 对于复杂的测试设置,考虑使用 DI 容器
测试组织
- 按功能或组件对测试进行分组
- 使用
[Trait("Category", "CategoryName")]进行分类 - 使用集合夹具对具有共享依赖项的测试进行分组
- 考虑使用输出助手(
ITestOutputHelper)进行测试诊断 - 使用事实/理论属性中的
Skip = "reason"有条件地跳过测试






