后端开发中如何写好单元测试和集成测试

chinaz
chinaz 正式会员超兽战士
发布于 2026-10-07 12:11 ·0 浏览 ·0 回复

后端写好测试的核心是"分工":单元测试用 mock 隔离掉数据库、网络、时钟,只验证单个类或函数的逻辑分支,单条执行控制在 10 毫秒内;集成测试用真实依赖(PostgreSQL 容器、真实 HTTP 栈、真实消息队列)验证跨组件协作。数量按测试金字塔控制在单元 70%、集成 20%、端到端 10%,覆盖率卡 70%~80%,核心计费与权限模块卡 90%,不要追 100%。

单元测试和集成测试有什么区别?

结论:区别不在于代码量多少,而在于是否替换了真实依赖。单元测试把数据库、RPC 客户端、系统时间全部替换成测试替身(test double,指 stub/mock/fake 这类假实现),只测被测单元本身;集成测试保留真实依赖,验证 SQL 方言、事务边界、JSON 序列化、HTTP 状态码这些"接缝"是否对得上。

以优惠券叠加为例:单元测试直接 new CouponCalculator(),传入满减券和折扣券的假对象,断言最终金额是 70 元;集成测试则真的往库里插两条券记录,走一次 HTTP 请求,断言响应体和数据库里的订单金额一致。前者挂了说明算法写错,后者挂了说明配置、SQL 或事务写错——两者抓的 bug 完全不同,谁也替代不了谁。

单元测试怎么写才不算白写?

结论:只测有分支的逻辑,一条用例对应一条分支,命名统一写成 方法名_场景_期望结果。

具体做法:

  1. 用 Given-When-Then 三段式组织:准备数据、调用方法、断言结果,三段之间空一行。
  2. 只 mock 直接依赖(DAO、RPC 客户端、Clock),不要 mock 值对象和 DTO,否则测试会变成"验证 mock 的调用次数",一重构就全红。
  3. 断言要具体:断言金额等于 7000 分,而不是 assertNotNull(result)。
  4. 边界值必须覆盖:0、-1、空集合、Integer.MAX_VALUE、超长字符串。异常分支至少写一条。

工具选型:Java 用 JUnit 5 + Mockito,Go 用标准库 testing 加接口打桩,Python 用 pytest + unittest.mock。反例是给 getter/setter、Lombok 生成的方法写测试——这只抬高覆盖率数字,不产生任何保护。

集成测试怎么做才能既真实又快?

结论:用 Testcontainers 起真实数据库容器(PostgreSQL 16 或 MySQL 8.0),用 @SpringBootTest + MockMvc 打真实 HTTP 栈,每个用例靠事务回滚或 TRUNCATE 保证隔离。

三个关键点:

  • 不要用 H2 模拟 PostgreSQL。索引行为、ON CONFLICT、JSONB、时区处理都不一样,本地绿线上炸是常态。
  • 容器要复用。单个容器冷启动约 3~8 秒,把容器声明为 static 并开启 @Testcontainers(REUSE),整套集成测试能从几分钟压到 1 分钟以内。
  • 第三方 HTTP 接口用 WireMock 打桩,而不是真连沙箱环境,否则测试会因为对方限流而随机失败。

集成测试的重点是那些单元测试碰不到的地方:事务传播(尤其 @Transactional 自调用失效)、数据库唯一约束冲突、分页排序、序列化时的时区与精度。

覆盖率到底卡多少?

结论:行覆盖率卡 70%~80%,增量覆盖率卡 80%,不要卡全量 100%。

覆盖率是下限不是目标,它只说明代码被执行过,不说明断言写对了。落地上更有效的是 CI 里卡新增代码覆盖率:Java 项目用 JaCoCo + SonarQube 的 New Code 门槛,Python 用 diff-cover,只要求本次改动的行达到 80%。

后端测试最常见的 5 个坑

  1. 测实现不测行为:断言内部方法调用次数,重构即全红。
  2. 测试间共享静态状态,执行顺序一变就挂。
  3. 直接用 LocalDateTime.now(),跨零点、跨时区必挂——改成注入 Clock。
  4. 用 Thread.sleep(3000) 等异步结果,改用 Awaitility 或轮询断言。
  5. 只写 happy path。真正出 bug 的是异常分支和边界值。

一句话收束:单元测试守住"逻辑对不对",集成测试守住"接缝通不通",前者要快而多,后者要真而少,两者比例和覆盖率门槛写进 CI,测试才算真正落地。

版权声明:本文来自 GJ站长论坛《后端开发中如何写好单元测试和集成测试》
原文链接:https://www.gj0.com/thread-273.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~