
Mockito 默认对所有方法进行空实现(返回默认值),因此直接 mock 类后,b() 调用的是被“清空”的 a(),而非你 stub 的行为;需显式启用部分模拟(partial mock)并指定哪些方法调用真实逻辑。
mockito 默认对所有方法进行空实现(返回默认值),因此直接 mock 类后,`b()` 调用的是被“清空”的 `a()`,而非你 stub 的行为;需显式启用部分模拟(partial mock)并指定哪些方法调用真实逻辑。
在使用 Mockito 对类进行模拟时,一个常见误区是认为:只要对某个方法(如 a())执行了 when(...).thenReturn(...),该方法在任何上下文(包括被同类中其他方法如 b() 内部调用)下都会返回设定值。但事实并非如此。
这是因为 mock(X.class) 创建的是全量模拟对象(full mock):所有非 final 的方法(包括 a() 和 b())均被 Mockito 替换为默认存根行为(如 int 方法返回 0)。即使你后续 stub 了 x.a(),该 stub 仅影响外部对 x.a() 的直接调用;而 x.b() 内部调用的 this.a() 实际触发的是模拟对象上未被 stub 的、已失效的 a() 实现(即返回 0 或原始默认值),而非你期望的 100。
✅ 正确做法是使用 部分模拟(Partial Mock),即让部分方法走真实逻辑,部分方法可被 stub:
X x = mock(X.class); when(x.a()).thenReturn(100); // stub a() → 返回 100 when(x.b()).thenCallRealMethod(); // 显式声明:调用真实的 b() 实现 assertEquals(100, x.b()); // ✅ 通过:b() 执行真实代码,内部调用的 a() 将命中上述 stub
⚠️ 注意事项:
-
thenCallRealMethod()仅对当前 mock 实例生效,且要求对应方法非final、非static、非private; - 受保护(
protected)方法在 Mockito 中可被正常 stub 和调用(前提是类可被继承,X非final); - 若
b()依赖a()的返回值做关键逻辑,更推荐的单元测试设计是:将a()提取为接口或依赖注入,避免对受测类自身方法进行部分模拟——这有助于提升可测性与设计清晰度; - 不建议滥用部分模拟:它往往暗示类职责过重或违反单一职责原则;优先考虑重构(如提取协作对象)而非依赖
thenCallRealMethod()。
总结:Mockito 的 mock 对象默认“屏蔽”全部方法行为;若需混合真实逻辑与模拟行为,必须显式声明 thenCallRealMethod(),并确保 stub 与真实调用链路径一致。










