1. Mock、Stub、Fake、Spy、Dummy 五种测试替身的本质区别和使用场景?请为每种替身举一个典型应用示例。
Mock、Stub、Fake、Spy、Dummy 五种测试替身的本质区别和使用场景是什么?请为每种替身举一个典型应用示例?
- 五种替身的定义与本质区别
- 各替身的典型应用场景
- 用示例说明替身选择的依据
五种测试替身按"是否真实实现、是否验证交互"区分。Dummy 是最轻的替身,仅用于占位传递参数,从不被真正使用,典型如传入一个不需用到的空对象。Stub 提供预置的返回数据,用于"喂数据"让被测单元走完分支,不验证交互,典型如网络接口返回固定 JSON。Fake 有真实可用的简略实现,能跑通业务逻辑但用轻量替代(如内存 Map 代替数据库),典型如内存版 Repository。Mock 既预置行为又验证交互是否发生(如 verify 某个方法被调用且参数正确),用于验证"协作是否正确"。Spy 包装真实对象,既走真实逻辑又记录调用,典型如包裹真实 HttpClient 并断言其被调用次数。本质区别在于:Dummy 不参与、Stub/Fake 只供数据、Mock/Spy 验证行为,其中 Spy 保留真实实现而 Mock 完全不依赖真实实现。
选择替身的关键是"测试关注什么":只关心返回数据用 Stub/Fake,关心调用关系用 Mock/Spy,仅占位用 Dummy。过度使用 Mock 会耦合实现细节,能真实地带数据走逻辑时优先用 Fake/Stub。
// Dummy:占位,不参与逻辑
PaymentService svc = new PaymentService(new DummyLogger());
// Stub:返回固定数据
when(api.getUser(1)).thenReturn(user("alice"));
// Spy:包装真实对象,记录调用
List<String> spy = spy(new ArrayList<>());
spy.add("a");
verify(spy).add("a");