本文介绍如何使用 mockito 对集合(特别是 set)中的每个对象进行 mock,并在调用目标方法后准确验证其内部方法是否被逐一执行,适用于 lombok 简化类结构的场景。
在单元测试中,若需验证某个方法是否对 Set 中的每个元素都执行了特定操作(如调用 bMethod()),关键在于:不能直接 mock 同一个对象多次加入 Set —— 因为 Mockito.mock(B.class) 创建的 mock 实例默认基于对象身份(identity)比较,而 HashSet 依赖 equals() 和 hashCode() 去重;若重复添加同一 mock,Set 实际只保留一个元素,导致验证失败。
正确的做法是:为 Set 中的每个逻辑元素创建独立的 mock 实例。以下是完整、可运行的 JUnit 5 + Mockito 测试示例(假设已引入 mockito-core 和 lombok):
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.HashSet;
import java.util.Set;
import static org.mockito.Mockito.verify;
public class ATest {
@Test
public void givenAWithBSet_whenAMethodIsCalled_thenCallBMethodOnAllBs() {
// GIVEN: 创建包含多个独立 B mock 的 Set
Set<B> bSet = new HashSet<>();
bSet.add(Mockito.mock(B.class)); // mock #1
bSet.add(Mockito.mock(B.class)); // mock #2
// 可按需添加更多(如循环生成)
A a = new A(bSet);
// WHEN: 执行被测方法
a.aMethod();
// THEN: 验证每个 mock 的 bMethod 恰好被调用一次
for (B b : a.getBSet()) {
verify(b).bMethod(); // 等价于 verify(b, times(1)).bMethod()
}
}
}
✅ 注意事项与最佳实践: