Stub关注返回值,用于状态验证;Mock关注调用行为,支持交互记录与断言,适用于行为验证。选择取决于测试目标:仅需控制输入输出用Stub,需验证调用细节则必须用Mock。

Stub 和 Mock 都是用来隔离被测代码、替代真实依赖的测试替身,但它们的关注点和使用方式有本质区别:Stub 关注“返回什么”,Mock 关注“怎么调用”。
Stub 是状态驱动的固定响应器
Stub 的核心是预设返回值,它不关心谁调用了它、调用了几次、传了什么参数,只按设定给出结果。
- 手动实现简单接口或类(比如继承真实类、实现接口),返回硬编码值
- 适合验证被测逻辑对特定输入的处理是否正确(状态验证)
- 例如:Stub 的
NameLoader总是返回一个含固定名字的列表,用来测试名字是否存在逻辑 - 不记录调用过程,无法断言“是否被调用”“被调用了几次”
Mock 是行为驱动的可验证模拟器
Mock 不仅能返回指定结果,还能记录交互过程,并支持后续断言——这是它最关键的区分点。
- 通常借助框架(如 Mockito)自动生成,无需手写实现类
- 支持定义“当调用某方法且参数满足条件时,返回什么”,也支持“期望该方法被调用一次/两次/不调用”
- 适合验证被测对象与依赖之间的协作是否符合预期(行为验证)
- 例如:Mock 的
Alarmer被设为“当名字不在服务器时必须调用reportAlarm”,测试最后会验证这个调用是否发生
什么时候选 Stub,什么时候选 Mock?
选择取决于你要验证什么:
立即学习“Java免费学习笔记(深入)”;
- 只需控制输入、检查输出结果 → Stub 更轻量、直观
- 需要确认依赖是否被调用、何时调用、传了什么参数 → 必须用 Mock
- 依赖逻辑简单、手写几行就能覆盖全部场景 → Stub 可行
- 依赖方法多、参数组合复杂,或要频繁调整响应逻辑 → Mock 更易维护
补充说明:它们不是互斥的,而是互补的
现代测试中,Mock 框架(如 Mockito)其实内置了 Stub 的能力:你可以用 when(...).thenReturn(...) 做 Stub 式响应,再用 verify(...).times(...) 做 Mock 式验证。所以实际开发中,Mock 已成为主流选择,而纯 Stub 多见于早期实践或极简场景。


















