1、.NET测试基础:为什么需要自动化测试、测试金字塔模型、单元测试与集成测试的区别、.NET测试生态概览

为什么我们需要自动化测试?

说实话,我见过太多项目在交付前一周陷入恐慌。开发人员熬夜改代码,测试人员疯狂点鼠标,项目经理在会议室里来回踱步。这种场景,我经历过不止一次。

自动化测试不是银弹,但它能解决一个核心问题:让代码变更变得安全。你想想看,当你重构一个方法时,怎么知道没把别的地方搞坏?手动跑一遍所有功能?不现实。自动化测试就像一张安全网,你改完代码,跑一遍测试,绿了,心里就有底了。

我个人习惯把自动化测试的价值总结为三点:

  • 快速反馈——几秒钟告诉你代码有没有问题
  • 回归保障——改旧代码时不怕引入新bug
  • 文档即代码——测试用例本身就是最好的使用说明

核心观点:没有自动化测试的项目,本质上是在靠「人肉」做回归测试。人总会累、会漏、会出错。机器不会。

测试金字塔模型

这个概念我第一次听是在2015年,当时觉得不就是分层嘛,有啥好讲的。后来在项目中吃了亏才明白——金字塔的形状决定了你的测试策略是否健康

测试金字塔分三层:

层级 类型 数量 速度 维护成本
顶层 端到端测试
中间层 集成测试 适中 中等 中等
底层 单元测试

为什么底层要写最多?因为单元测试跑得快、定位准。我曾经在一个项目中看到团队写了大量端到端测试,结果每次CI跑测试要40分钟,而且一挂就是一大片,根本不知道哪里出了问题。这就是典型的「倒金字塔」——反模式。

我的建议:单元测试占比70%以上,集成测试20%,端到端测试10%以内。这个比例不是绝对的,但偏离太多就要警惕了。

单元测试与集成测试的区别

这个问题我面试时经常问。很多人能背出定义,但一到实际写代码就混淆。

单元测试——测试的是「一个单元」。在.NET里,通常是一个类的一个方法。它不依赖外部资源(数据库、文件系统、网络)。说白了,就是把你写的逻辑单独拎出来测。

集成测试——测试的是「多个单元协作」。比如一个Service调用了Repository,Repository又操作了数据库。这时候测的是它们能不能配合好。

举个例子:

// 单元测试:只测计算逻辑,不碰数据库
[Fact]
public void CalculateDiscount_WhenTotalOver100_ShouldReturn10Percent()
{
    var service = new DiscountService();
    var result = service.CalculateDiscount(150);
    Assert.Equal(15, result);
}

// 集成测试:真的去查数据库
[Fact]
public async Task GetOrder_WhenOrderExists_ShouldReturnOrderFromDatabase()
{
    // 这里需要真实的数据库连接
    var repo = new OrderRepository(connectionString);
    var order = await repo.GetByIdAsync(1);
    Assert.NotNull(order);
}

注意:单元测试里不要连数据库。我见过有人把单元测试写成集成测试,结果测试跑得慢不说,还经常因为数据库连接失败而挂掉。这完全失去了单元测试的意义。

.NET测试生态概览

嗯,这里我简单梳理一下。.NET的测试生态其实挺成熟的,主要分三块:

  • 测试框架:xUnit(我推荐)、NUnit、MSTest。xUnit是现在的主流,设计更现代,扩展性好。
  • 模拟框架:Moq、NSubstitute、FakeItEasy。我个人习惯用Moq,社区活跃,文档全。
  • 辅助工具:FluentAssertions(让断言更可读)、AutoFixture(自动生成测试数据)、Coverlet(覆盖率统计)。

还有一个不得不提的是Testcontainers。这个库可以在集成测试中启动Docker容器,比如测试需要SQL Server,直接拉一个镜像起来,测试完自动销毁。我在项目中用过,非常方便。

一句话总结:自动化测试不是可选项,是专业开发的标配。测试金字塔帮你规划策略,分清单元测试和集成测试让你少走弯路,.NET生态提供了足够好的工具。剩下的,就是动手写了。

下一章我会带你搭建第一个xUnit测试项目,咱们手把手来。到时候你会发现,写测试其实没那么难。