单元测试入门:从第一个断言开始

举报
yd_213156404 发表于 2026/11/11 00:42:21 2026/11/11
【摘要】 本文介绍单元测试的基本概念、AAA 模式、覆盖要点与常见误区,带你从第一个断言开始写下第一个测试。

写给还没写过测试的你

很多开发者第一次听到“单元测试”,脑子里浮现的是密密麻麻的测试框架文档和复杂的 Mock 配置,于是把这件事一推再推。其实单元测试的起点非常小:给一个函数写一段代码,验证它在给定输入下是不是返回了预期的结果。就这么简单。

什么是单元测试

单元测试是针对代码中最小可测试单元的验证,通常是一个函数或一个类的方法。它有三个特点:粒度小、运行快、相互独立。一个好的单元测试不依赖数据库、不调用外部接口、不读取文件,只关心“这段逻辑本身对不对”。

举个例子,一个计算订单折扣的函数,根据会员等级返回不同的折扣价。它的行为完全由输入决定,这就是最适合写单元测试的地方。

第一个测试:AAA 模式

写测试有一个非常实用的结构,叫 AAA,也就是准备(Arrange)、执行(Act)、断言(Assert)。

@Test
void vipUserGetsTwentyPercentOff() {
    // Arrange:准备数据
    DiscountCalculator calculator = new DiscountCalculator();
    // Act:执行被测方法
    double price = calculator.applyDiscount(100.0, "VIP");
    // Assert:断言结果
    assertEquals(80.0, price, 0.001);
}

三行代码,意思一目了然:准备一个计算器,对 100 元订单按 VIP 折扣计算,断言结果是 80 元。测试失败时,断言会精确告诉你“期望 80,实际是多少”,定位问题只需要看这一处。

测试应该覆盖什么

新手常问:到底要测多少才够?不必追求一步到位,先抓住三类情况:

  1. 正常路径:最常见的输入,比如普通会员、VIP 会员分别享受什么折扣。
  2. 边界值:价格为 0、刚好达到满减门槛、超过上限的金额,这些地方最容易藏 bug。
  3. 异常情况:传入非法的会员等级、负数金额时,函数是抛异常还是返回默认值,行为要符合预期。

覆盖这三类,大部分核心逻辑就有了基本保障。剩下的可以在修 bug 时顺手补上:每修一个 bug,先写一个能复现它的测试,再改代码,bug 就很难卷土重来。

四个容易踩的坑

只测“快乐路径”。 只验证正常输入,边界和异常全靠线上用户发现,测试就失去了大半价值。

测试写得比代码还复杂。 如果一个测试需要十几行准备数据才能跑起来,往往是被测代码的依赖太多、职责不清。先重构代码,让它更容易被测试,而不是给测试打补丁。

过度使用 Mock。 Mock 是为了隔离外部依赖,不是为了把所有协作者都换成假对象。Mock 太多,测试验证的只是“假对象按剧本演出”,代码一改就全线飘红。

把测试当成负担。 测试不是写完功能后的“附加作业”,而是开发过程的一部分。先写测试再写实现听起来激进,但哪怕只是“实现完立刻补测试”,也比拖到上线前集中补要轻松得多。

从哪里开始

如果你所在的项目还没有测试,不用想着一夜之间补齐全部覆盖率。选一个最核心、最稳定的纯函数,比如价格计算、日期换算、字符串处理,给它写三五个测试,跑通后把测试命令接进持续集成。从此每次提交代码,都有一个自动的“守门员”帮你盯着回归问题。

单元测试的价值不是那一行绿色的通过提示,而是它带来的底气:敢重构、敢升级依赖、敢在深夜合并代码。因为你知道,一旦改坏了什么,测试会在第一时间告诉你。

从第一个断言开始,写下你的第一个测试吧。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。