Mockito无法与Predicate函数配合使用问题排查
首先把你的测试代码和被测试方法整理出来,方便咱们分析问题:
测试代码:
@Test public void testListIntersectionByRoleIsEmpty() { when(sfa.getRequesterGroups()).thenReturn(testRoles); when(shareableMetacard.getAccessGroups()).thenReturn(mockedRoleSet); assertTrue(sfa.sharedByGroup().test(shareableMetacard)); }
被测试方法:
@VisibleForTesting Predicate<Share> sharedByGroup() { return metacard -> !metacard .getAccessGroups() .stream() .filter(getRequesterGroups()::contains) .collect(Collectors.toList()) .isEmpty(); }
接下来咱们一步步排查Mockito失效的可能原因:
1. 确认Mock实例是否正确初始化
你得确保sfa和shareableMetacard都是Mockito创建的Mock对象,而不是真实实例:
- 如果用JUnit 4,要在测试类上添加
@RunWith(MockitoJUnitRunner.class),再给两个对象加上@Mock注解; - 如果是JUnit 5,添加
@ExtendWith(MockitoExtension.class),同样用@Mock标记这两个对象; - 或者手动调用
Mockito.mock(Sfa类名.class)和Mockito.mock(ShareableMetacard类名.class)创建Mock。
要是用了真实实例,Mockito的when(...)根本拦截不了方法调用,Stub自然不会生效。
2. 检查测试数据是否存在交集
你的测试断言是assertTrue(...),而被测试方法的逻辑是两个集合有交集时返回true。如果testRoles和mockedRoleSet完全没有重叠元素,那不管Mockito工作与否,这个断言都会失败。
建议在测试里加一行调试代码,打印两个集合的内容,确认它们确实有交集:
System.out.println("测试用角色集合:" + testRoles); System.out.println("元卡片权限集合:" + mockedRoleSet);
3. 验证getRequesterGroups()的调用来源
被测试方法里的getRequesterGroups()是调用当前sfa实例的方法,你得确认:测试中Stub的sfa.getRequesterGroups()和被测试方法里调用的是同一个实例。
比如,如果sharedByGroup()里的getRequesterGroups()调用了静态方法、或者其他未被Mock的实例方法,那Mockito的Stub肯定不会起作用。
4. 优化被测试方法逻辑(可选,简化排查)
你当前用stream().filter(...).collect(Collectors.toList()).isEmpty()判断交集的方式,可以简化成更高效直观的anyMatch(),这样逻辑更清晰,也方便调试:
@VisibleForTesting Predicate<Share> sharedByGroup() { Set<String> requesterGroups = getRequesterGroups(); return metacard -> metacard.getAccessGroups() .stream() .anyMatch(requesterGroups::contains); }
这种写法不需要收集整个列表,找到第一个匹配元素就返回,性能更好,也能让你更直接地查看requesterGroups的内容是否正确。
5. 用Mockito验证确认Stub是否被调用
你可以在测试末尾加一段验证代码,确认Mock对象的方法是否被正确调用:
verify(sfa, times(1)).getRequesterGroups(); verify(shareableMetacard, times(1)).getAccessGroups();
如果验证失败,说明你的方法根本没调用这些Mock方法,那就要检查方法调用的路径是否正确了。
内容的提问来源于stack exchange,提问作者John Lippson

