单元测试是针对软件中最小可测试单元进行验证的测试方法,在.NET开发中,通常是对单个方法、类或者独立功能模块进行正确性校验,确保单个逻辑单元的输出符合预期。它可以提前发现代码中的逻辑问题,避免问题扩散到后续集成或生产环境,同时也有利于代码的重构和维护。

.NET单元测试的核心概念
在.NET中编写单元测试,需要理解几个基础概念:
- 测试项目:独立于主业务项目的类库项目,专门用于存放测试代码,避免测试逻辑和业务代码耦合。
- 测试类:存放测试方法的类,通常一个测试类对应一个被测试的业务类。
- 测试方法:单个具体的测试用例,用于验证某一个特定场景下的代码逻辑。
- 断言:测试中的核心判断逻辑,用于比对实际执行结果和预期结果是否一致。
使用xUnit编写第一个测试
1. 创建测试项目
首先创建一个.NET的控制台应用作为被测试的主项目,然后在同一解决方案下添加xUnit测试项目。创建完成后,测试项目会自动引用xUnit相关的NuGet包,同时需要手动添加对主项目的引用。
2. 编写被测试的业务代码
在主项目中添加一个简单的计算器类,代码如下:
// 主项目中的计算器类
namespace UnitTestDemo
{
public class Calculator
{
// 加法方法
public int Add(int a, int b)
{
return a + b;
}
}
}
3. 编写xUnit测试代码
在xUnit测试项目中添加测试类,编写针对Add方法的测试用例:
using Xunit;
using UnitTestDemo;
namespace xUnitTestProject
{
public class CalculatorTests
{
// 标记该方法为测试方法
[Fact]
public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
{
// 准备测试数据
var calculator = new Calculator();
int a = 3;
int b = 5;
int expected = 8;
// 执行被测试方法
int actual = calculator.Add(a, b);
// 断言结果是否符合预期
Assert.Equal(expected, actual);
}
}
}
4. 执行测试
在Visual Studio中可以通过测试资源管理器运行测试,也可以使用命令行执行:
dotnet test
如果测试通过,命令行会输出测试成功的相关信息。
使用MSTest编写第一个测试
1. 创建MSTest测试项目
同样先创建主项目,然后添加MSTest测试项目,创建后测试项目会自动引用MSTest相关的NuGet包,添加对主项目的引用。
2. 编写MSTest测试代码
使用和xUnit相同的被测试Calculator类,编写MSTest的测试代码:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UnitTestDemo;
namespace MSTestProject
{
[TestClass]
public class CalculatorTests
{
// 标记该方法为测试方法
[TestMethod]
public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
{
// 准备测试数据
var calculator = new Calculator();
int a = 3;
int b = 5;
int expected = 8;
// 执行被测试方法
int actual = calculator.Add(a, b);
// 断言结果是否符合预期
Assert.AreEqual(expected, actual);
}
}
}
3. 执行测试
MSTest的执行方式和xUnit类似,同样可以通过测试资源管理器或者命令行运行,执行后查看测试结果即可。
xUnit和MSTest的简单对比
| 对比项 | xUnit | MSTest |
|---|---|---|
| 测试类特性标记 | 不需要额外类标记 | 需要[TestClass]标记 |
| 测试方法特性标记 | [Fact] | [TestMethod] |
| 断言类 | Xunit.Assert | Microsoft.VisualStudio.TestTools.UnitTesting.Assert |
| 社区活跃度 | 较高,开源生态丰富 | 微软官方维护,和Visual Studio集成度高 |
编写单元测试的注意事项
- 测试方法命名建议清晰体现测试场景,比如方法名包含被测试方法、输入条件、预期结果。
- 单个测试方法只验证一个逻辑点,避免一个测试方法包含多个断言导致问题定位困难。
- 测试代码也需要维护,和业务代码一样保证可读性和规范性。