Mockito模拟List在单元测试中遍历异常的原因与解决
Mock List导致单元测试异常的原因与修复方案
问题根源
你只Mock了listMock.get(0)的返回值,但Mockito生成的Mock对象中,未显式指定行为的方法会返回对应类型的默认值:
isEmpty():boolean类型默认返回false,所以你的assertFalse(listMock.isEmpty())能通过,但这不是因为列表真的包含元素size():int类型默认返回0,导致Sum.sum()方法中的for循环条件i < list.size()(即i < 0)不成立,循环完全没执行,sum保持初始值0,这就是测试返回0而非预期42的核心原因
修复方案
方案1:Mock所有被调用的方法
为Sum.sum()中用到的isEmpty()、size()、get()方法都指定预期行为:
@Test void sum_single() { final List<Integer> listMock = Mockito.mock(List.class); Mockito.when(listMock.isEmpty()).thenReturn(false); Mockito.when(listMock.size()).thenReturn(1); Mockito.when(listMock.get(0)).thenReturn(42); assertEquals(42, Sum.sum(listMock)); }
方案2:使用Spy包装真实List
如果不想手动Mock每个方法,可以用Mockito Spy包装一个真实的List实例,未自定义的方法会自动调用真实List的逻辑:
@Test void sum_single() { final List<Integer> realList = new ArrayList<>(); realList.add(42); final List<Integer> listSpy = Mockito.spy(realList); assertEquals(42, Sum.sum(listSpy)); }
方案3:连缀简化Mock代码
可以将多个方法的Mock逻辑连缀起来,让代码更简洁:
@Test void sum_single() { final List<Integer> listMock = Mockito.mock(List.class); Mockito.when(listMock.isEmpty()).thenReturn(false) .when(listMock.size()).thenReturn(1) .when(listMock.get(0)).thenReturn(42); assertEquals(42, Sum.sum(listMock)); }
额外说明:测试中
assertFalse(listMock.isEmpty())和assertEquals(42, listMock.get(0))能通过,只是因为前者命中了Mockito的默认返回值,后者是你显式指定的行为,但这两个验证并没有覆盖Sum.sum()实际依赖的size()方法,才导致测试结果不符合预期。
内容的提问来源于stack exchange,提问作者knittl
相关产品推荐
相关产品推荐

