Mockito.verify() 验证方法调用次数需作用于 mock 对象,配合 times()、never() 等验证器;必须在被测逻辑执行后调用,统计全局累计次数,并显式使用 eq() 或 any() 等匹配器确保参数精准匹配。

使用 Mockito 验证方法调用次数,核心是 Mockito.verify() 配合 times()、atLeast()、atMost()、never() 等验证器。关键前提是:被验证的方法必须是在 mock 对象上被调用的(即该对象是用 mock() 或 @Mock 创建的),而不是真实对象。
确保目标方法调用的是 mock 对象
如果误对真实对象调用 verify(),会抛出 CannotVerifyStubOnlyMockException;如果没调用过就 verify,会失败并提示“Wanted but not invoked”。所以先确认:
- 被测类中依赖的对象已替换为 mock 实例(例如通过构造函数注入或 setter 注入)
- 测试中只对 mock 对象的方法做 verify,不 verify 真实实现类或 spy 对象的未打桩方法
- 调用发生在被测逻辑执行过程中(如调用
service.process()),而非手动调用
基本调用次数验证写法
验证某方法被调用了恰好 n 次:
verify(mockDao).save(any(User.class)); // 默认 times(1)
verify(mockDao, times(1)).save(any(User.class));
verify(mockDao, times(3)).updateStatus(eq("ACTIVE"));
verify(mockDao, never()).delete(anyLong());
常用验证器:
-
times(n):精确 n 次 -
atLeastOnce():≥1 次(等价于times(1)) -
atLeast(n):≥n 次 -
atMost(n):≤n 次 -
never():0 次
注意 verify 的作用域和顺序
Mockito 的 verify 是“全局累计”计数,不是仅限于最近一次调用。它统计整个测试方法执行期间所有匹配调用的总次数。例如:
- 如果被测方法内部循环调用了 5 次
logger.info(),那么verify(logger, times(5)).info(anyString())才通过 - 不能用多次
verify(..., times(1))来“分段断言”,那样会重复计数导致失败 - verify 必须在被测逻辑执行 之后 调用;放在之前会因无调用而失败
结合参数匹配与调用次数精准验证
避免因参数不匹配导致误判。建议显式指定参数约束:
- 用
eq(value)替代直接传字面量(尤其 String、null、自定义对象) - 用
any()/anyString()等通配符时,确保语义合理 - 若需验证不同参数的调用各几次,可多次 verify + 不同匹配器(但注意总次数仍累计)
示例:
service.createUser("Alice");
service.createUser("Bob");
service.createUser("Alice");
verify(userRepository, times(2)).findByUsername(eq("Alice")); // ✅
verify(userRepository, times(1)).findByUsername(eq("Bob")); // ✅
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











