dotnet-test-frameworks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

.NET Test Framework Reference

.NET 测试框架参考

Language-specific detection patterns for .NET test frameworks (MSTest, xUnit, NUnit, TUnit).
针对.NET测试框架(MSTest、xUnit、NUnit、TUnit)的语言专属检测模式。

Test File Identification

测试文件识别

FrameworkTest class markersTest method markers
MSTest
[TestClass]
[TestMethod]
,
[DataTestMethod]
xUnit(none — convention-based)
[Fact]
,
[Theory]
NUnit
[TestFixture]
[Test]
,
[TestCase]
,
[TestCaseSource]
TUnit
[ClassDataSource]
[Test]
框架测试类标记测试方法标记
MSTest
[TestClass]
[TestMethod]
,
[DataTestMethod]
xUnit(无,基于约定识别)
[Fact]
,
[Theory]
NUnit
[TestFixture]
[Test]
,
[TestCase]
,
[TestCaseSource]
TUnit
[ClassDataSource]
[Test]

Assertion APIs by Framework

各框架断言API

CategoryMSTestxUnitNUnit
Equality
Assert.AreEqual
Assert.Equal
Assert.That(x, Is.EqualTo(y))
Boolean
Assert.IsTrue
/
Assert.IsFalse
Assert.True
/
Assert.False
Assert.That(x, Is.True)
Null
Assert.IsNull
/
Assert.IsNotNull
Assert.Null
/
Assert.NotNull
Assert.That(x, Is.Null)
Exception
Assert.Throws<T>()
/
Assert.ThrowsExactly<T>()
Assert.Throws<T>()
Assert.That(() => ..., Throws.TypeOf<T>())
Collection
CollectionAssert.Contains
Assert.Contains
Assert.That(col, Has.Member(x))
String
StringAssert.Contains
Assert.Contains(str, sub)
Assert.That(str, Does.Contain(sub))
Type
Assert.IsInstanceOfType
Assert.IsAssignableFrom
Assert.That(x, Is.InstanceOf<T>())
Inconclusive
Assert.Inconclusive()
skip via
[Fact(Skip)]
Assert.Inconclusive()
Fail
Assert.Fail()
Assert.Fail()
(.NET 10+)
Assert.Fail()
Third-party assertion libraries:
Should*
(Shouldly),
.Should()
(FluentAssertions / AwesomeAssertions),
Verify()
(Verify).
分类MSTestxUnitNUnit
相等判断
Assert.AreEqual
Assert.Equal
Assert.That(x, Is.EqualTo(y))
布尔判断
Assert.IsTrue
/
Assert.IsFalse
Assert.True
/
Assert.False
Assert.That(x, Is.True)
空值判断
Assert.IsNull
/
Assert.IsNotNull
Assert.Null
/
Assert.NotNull
Assert.That(x, Is.Null)
异常判断
Assert.Throws<T>()
/
Assert.ThrowsExactly<T>()
Assert.Throws<T>()
Assert.That(() => ..., Throws.TypeOf<T>())
集合判断
CollectionAssert.Contains
Assert.Contains
Assert.That(col, Has.Member(x))
字符串判断
StringAssert.Contains
Assert.Contains(str, sub)
Assert.That(str, Does.Contain(sub))
类型判断
Assert.IsInstanceOfType
Assert.IsAssignableFrom
Assert.That(x, Is.InstanceOf<T>())
不确定结果
Assert.Inconclusive()
通过
[Fact(Skip)]
跳过
Assert.Inconclusive()
强制失败
Assert.Fail()
Assert.Fail()
(.NET 10+)
Assert.Fail()
第三方断言库:
Should*
(Shouldly)、
.Should()
(FluentAssertions / AwesomeAssertions)、
Verify()
(Verify)。

Sleep/Delay Patterns

睡眠/延迟模式

PatternExample
Thread sleep
Thread.Sleep(2000)
Task delay
await Task.Delay(1000)
SpinWait
SpinWait.SpinUntil(() => condition, timeout)
模式示例
线程睡眠
Thread.Sleep(2000)
任务延迟
await Task.Delay(1000)
自旋等待
SpinWait.SpinUntil(() => condition, timeout)

Skip/Ignore Annotations

跳过/忽略注解

FrameworkAnnotationWith reason
MSTest
[Ignore]
[Ignore("reason")]
xUnit
[Fact(Skip = "reason")]
(reason is required)
NUnit
[Ignore("reason")]
(reason is required)
TUnit
[Skip("reason")]
(reason is required)
Conditional
#if false
/
#if NEVER
(no reason possible)
框架注解支持填写原因
MSTest
[Ignore]
[Ignore("reason")]
xUnit
[Fact(Skip = "reason")]
(必须填写原因)
NUnit
[Ignore("reason")]
(必须填写原因)
TUnit
[Skip("reason")]
(必须填写原因)
条件编译
#if false
/
#if NEVER
(无法填写原因)

Exception Handling — Idiomatic Alternatives

异常处理——惯用替代方案

When a test uses
try
/
catch
to verify exceptions, suggest the framework-native alternative:
MSTest:
csharp
// Instead of try/catch (matches exact type):
var ex = Assert.ThrowsExactly<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

// Or (also matches derived types):
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);
xUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);
NUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.That(ex.Message, Is.EqualTo("Order must contain at least one item"));
当测试使用
try
/
catch
验证异常时,推荐使用框架原生的替代方案:
MSTest:
csharp
// 替代try/catch(匹配 exact 类型):
var ex = Assert.ThrowsExactly<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

// 或者(也匹配派生类型):
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);
xUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);
NUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.That(ex.Message, Is.EqualTo("Order must contain at least one item"));

Mystery Guest — Common .NET Patterns

神秘访客(Mystery Guest)——常见.NET模式

Smell indicatorWhat to look for
File system
File.ReadAllText
,
File.Exists
,
File.WriteAllBytes
,
Directory.GetFiles
,
Path.Combine
with hard-coded paths
Database
SqlConnection
,
DbContext
(without in-memory provider),
SqlCommand
Network
HttpClient
without
HttpMessageHandler
override,
WebRequest
,
TcpClient
Environment
Environment.GetEnvironmentVariable
,
Environment.CurrentDirectory
Acceptable
MemoryStream
,
StringReader
,
InMemory
database providers, custom
DelegatingHandler
坏味道指标排查点
文件系统带硬编码路径的
File.ReadAllText
File.Exists
File.WriteAllBytes
Directory.GetFiles
Path.Combine
数据库
SqlConnection
、未使用内存提供器的
DbContext
SqlCommand
网络请求未重写
HttpMessageHandler
HttpClient
WebRequest
TcpClient
环境变量
Environment.GetEnvironmentVariable
Environment.CurrentDirectory
可接受用法
MemoryStream
StringReader
、内存数据库提供器、自定义
DelegatingHandler

Integration Test Markers

集成测试标记

Recognize these as integration tests (adjust smell severity accordingly):
  • Class name contains
    Integration
    ,
    E2E
    ,
    EndToEnd
    , or
    Acceptance
  • [TestCategory("Integration")]
    (MSTest)
  • [Trait("Category", "Integration")]
    (xUnit)
  • [Category("Integration")]
    (NUnit)
  • Project name ending in
    .IntegrationTests
    or
    .E2ETests
以下特征可识别为集成测试(对应调整坏味道严重等级):
  • 类名包含
    Integration
    E2E
    EndToEnd
    Acceptance
  • [TestCategory("Integration")]
    (MSTest)
  • [Trait("Category", "Integration")]
    (xUnit)
  • [Category("Integration")]
    (NUnit)
  • 项目名以
    .IntegrationTests
    .E2ETests
    结尾

Setup/Teardown Methods

Setup/Teardown 方法

FrameworkSetupTeardown
MSTest
[TestInitialize]
or constructor
[TestCleanup]
or
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
xUnitconstructor
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
NUnit
[SetUp]
[TearDown]
MSTest (class)
[ClassInitialize]
[ClassCleanup]
NUnit (class)
[OneTimeSetUp]
[OneTimeTearDown]
xUnit (class)
IClassFixture<T>
fixture's
Dispose
框架SetupTeardown
MSTest
[TestInitialize]
或构造函数
[TestCleanup]
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
xUnit构造函数
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
NUnit
[SetUp]
[TearDown]
MSTest(类级别)
[ClassInitialize]
[ClassCleanup]
NUnit(类级别)
[OneTimeSetUp]
[OneTimeTearDown]
xUnit(类级别)
IClassFixture<T>
fixture 的
Dispose
方法