第 09 章 第 09 章 单元测试与可测试性:敢改别人的代码(已拆分为多篇)

原章约 87375 字符,较长。已按主题拆分为以下小节,单篇约 15 分钟可读。

本节导航


原章开头引子

你现在是那个订单服务的 owner。3 万行代码,0 个测试。 leader 走过来说:「加个功能,订单支持优惠券。」 你知道该改哪里 —— OrderServiceImpl.createOrder() 第 147 行往下,加一段算价。但你不敢改,因为你没有任何办法验证改完之后别的地方会不会炸。 于是你打开这个项目里唯一存在的 OrderServiceImplTest.java,看到的是这个:

@SpringBootTest                                  // 启动完整 Spring 容器
public class OrderServiceImplTest {
    @Autowired
    private OrderService orderService;           // 真 Bean,连真 MySQL
 
    @Test
    public void testCreateOrder() {
        // ...一堆断言
    }
}

跑一次 47 秒。47 秒里大概有 8 秒是 JVM 启动、20 秒是 Spring 容器装配和 classpath 扫描、剩下的是连数据库和 IO 等待。

问题 1(先想三十秒): 3 万行代码,你打算写多少个这样的测试?全量跑一遍要多久?跑不完的测试,跟没有测试的区别是什么?

这道题的答案不是”多写点测试”或者”优化一下”。它逼你承认一件事:测试的瓶颈从来不是”会不会写”,而是”代码允不允许你写”。 那个 47 秒的测试之所以要启动整个容器、连真实数据库,不是因为写它的人懒,而是因为 OrderServiceImpl 里的依赖是写死的 —— 你没法只测它一个类。

所以这一章不讲”怎么写测试”。讲怎么让代码变得可以被测试,以及拿到一堆测不了的代码时,怎么用最小成本撬开一条缝。