本文介绍如何使用mockito对set集合中的每个对象进行mock,并在单元测试中准确验证其方法是否被逐一调用,避免因set去重机制导致的验证失败。
在单元测试中,当我们需要验证一个集合(如 Set)中每个元素的方法是否被调用时,不能直接使用相同 mock 实例多次添加进 Set——因为 Mockito.mock(B.class) 创建的 mock 对象默认基于 Object#hashCode() 和 equals() 进行比较,而默认 mock 的 identity-based 行为会导致多个相同 mock 被视为重复元素,最终 Set 中仅保留一个。这将使 a.aMethod() 实际只遍历一次,导致后续 verify() 断言失败或漏检。
✅ 正确做法是:为 Set 中每个位置创建独立的 mock 实例。如下所示:
@Test
public void givenAWithBSet_whenAMethodIsCalled_thenCallBMethodOnAllBs() {
Set bSet = new HashSet();
// 创建多个独立的 mock B 实例(不可复用同一个 mock!)
bSet.add(Mockito.mock(B.class));
bSet.add(Mockito.mock(B.class));
// 或使用循环批量创建(推荐用于数量较多场景)
// for (int i = 0; i < 5; i++) {
// bSet.add(Mockito.mock(B.class));
// }
A a = new A(bSet);
// 执行待测方法
a.aMethod();
// 验证每个 mock 的 bMethod 是否被调用恰好一次
for (B b : a.getBSet()) {
verify(b).bMethod(); // 等价于 verify(b, times(1)).bMethod()
}
// (可选)进一步确保无其他意外调用
a.getBSet().forEach(Mockito::verifyNoMoreInteractions);
}
⚠️ 注意事项: