Skip to content

Test Doubles 5 种 = 测试替身的智慧 ​

解决什么问题:不知道该用 Mock 还是 Fake—— Test Doubles 5 种各有适用场景,错用 = 测试失效。

业务问题 ​

真实场景 ​

场景 1:Mock 一切的代价

python
# 反模式:Mock 一切
def test_order_service():
    mock_db = Mock()
    mock_payment = Mock()
    mock_email = Mock()
    mock_logger = Mock()
    # 测的不是真实逻辑
    # 是"我告诉 mock 返回什么"

问题:测试与生产脱节,重构就坏。

Test Doubles 5 种(Google 定义) ​

类型用途例子
Dummy占位参数None、""
Fake可工作的假实现内存数据库
Stub返回预设值stub.get() returns 42
Spy记录调用"调用了 get() 1 次"
Mock验证行为"必须调 send_email()"

核心概念 ​

何时用什么 ​

能用真实 → 用真实(首选)
真实对象太慢 → Fake
真实对象有副作用 → Stub
要验证调用 → Spy
要验证行为契约 → Mock

反模式 ​

反模式后果
Mock 一切测试与生产脱节
测实现而非行为重构就坏
Mock 私有方法测的是细节

工程实践 ​

决策树 ​

能用真实对象吗?
  - 是 → 用真实
  - 否(太慢/不可靠) → 继续
对象只是返回数据?
  - 是 → Fake(内存实现)
对象调用外部系统?
  - 是 → Stub(预设返回值)
要验证是否被调用?
  - 是 → Spy
要验证调用顺序/参数?
  - 是 → Mock

与 L 层对位 ​

性能指标 ​

指标健康值
Fake 占比> 50%
Mock 占比< 20%
测试稳定性flaky < 1%

关键洞察 ​

  1. Fake > Mock——能 Fake 就 Fake。
  2. Mock 测行为,不是实现——别测私有方法。
  3. 真实对象能用就用——最可靠。
  4. 与 cybernetics 同构——Ch 6 §6.3 解耦 = 测试替身 = 隔离被测单元。

从名家方法论与工程化思路中蒸馏出自己的工程体系。