JUnit中Mock for循环内if条件关联方法调用未触发如何解决
问题根因
你遇到的目标方法未被调用的问题主要来自三个核心错误:
- 迭代器被提前消费耗尽
你在测试方法中先写了for (LifeProduct mockProduct : mockList)遍历mock列表,而你在setUp中仅给迭代器Stub了hasNext() -> true, false的返回序列,这一轮遍历已经把仅有的一次有效返回用完了。后续业务方法prune内部再次遍历mockList时,hasNext()直接返回false,根本不会进入循环执行if分支。 - Mock对象的getter未做Stub
mockProduct是Mockito生成的Mock对象,调用setProductAnalyticsIdentifier没有实际作用——Mock对象的setter默认是空实现,也不会自动存储字段值。你没有StubgetProductAnalyticsIdentifier()的返回值,该方法默认返回int类型的默认值0,导致deleteAnnuity = 0>10014结果为false,不会触发后续删除方法。 - 测试逻辑位置错误
你把业务方法调用、验证逻辑都放到了遍历mockList的循环内部,逻辑顺序完全错误。
修复后的测试代码
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); // 迭代器仅在业务方法内部被遍历一次,此处Stub保留即可 when(mockList.iterator()).thenReturn(mockIterator); when(mockIterator.hasNext()).thenReturn(true, false); when(mockIterator.next()).thenReturn(mockProduct); } @Test public final void testPrune() throws Exception { // 1. 正确Stub mockProduct的返回值,不需要提前遍历mockList when(mockProduct.getProductAnalyticsIdentifier()).thenReturn(99999999); // 如果需要测试寿险删除分支,还要补充下面的Stub // LifeInsurance mockInsurance = mock(LifeInsurance.class); // when(mockProduct.getLifeInsurance()).thenReturn(mockInsurance); // when(mockInsurance.getHighLevelLifeInsuranceGroupName()).thenReturn("string"); // 2. Stub service的空方法 doNothing().when(annuityService).deleteAnnuityById(anyInt()); // doNothing().when(lifeInsuranceService).deleteLifeInsuranceById(anyInt()); // 3. 执行业务方法 List<LifeProduct> response = lifeProductDelegate.prune(mockList); // 4. 结果验证 assertNotNull(response); verify(annuityService).deleteAnnuityById(99999999); // 用具体值校验比anyInt更严谨 // verify(lifeInsuranceService).deleteLifeInsuranceById(99999999); }
通用排查步骤
- 确认你Stub的迭代器返回次数和实际遍历次数一致,不要提前消费Mock集合的迭代器
- 对Mock对象的取值方法做明确Stub,不要依赖setter对Mock对象赋值
- 如果if判断有多个链式调用(比如
getLifeInsurance().getXXX()),要确保每一层对象的方法都正确Stub,避免出现空指针或返回值不符合预期的问题 - 验证方法调用必须放在业务方法执行之后,且参数匹配规则正确
内容的提问来源于stack exchange,提问作者joshskkim
相关产品推荐
相关产品推荐

