如何为含break语句的while循环编写Mockito JUnit 5测试用例?
解决JUnit 5测试带break的while循环无限执行问题
核心思路
要让循环正常终止并覆盖所有代码路径,关键是让Mock的findAll()方法先返回有数据的列表,最后返回空列表。这样deleteRecord()会先返回大于0的数值触发循环,最后返回0触发break退出循环。
具体实现方案
1. 使用Mockito链式thenReturn()模拟多次调用结果
Mockito支持通过链式调用thenReturn()指定方法多次调用的不同返回值,顺序对应实际调用次数:
@ExtendWith(MockitoExtension.class) class RecordServiceTest { @Mock private RecordRepository recordRepository; @InjectMocks private RecordService recordService; @Test void testDeleteRecordsWithData() { // 第一次调用findAll返回1条数据,第二次返回空列表 when(recordRepository.findAll()) .thenReturn(List.of(new Record())) .thenReturn(Collections.emptyList()); // 执行测试:循环会执行2次deleteRecord后终止 recordService.deleteRecords(); // 验证调用逻辑是否符合预期 verify(recordRepository, times(2)).findAll(); verify(recordRepository, times(1)).deleteAll(anyList()); } // 覆盖「一开始就无数据」的代码路径 @Test void testDeleteRecordsWithoutData() { // 直接返回空列表,deleteRecord返回0,循环直接退出 when(recordRepository.findAll()).thenReturn(Collections.emptyList()); recordService.deleteRecords(); // 验证调用逻辑 verify(recordRepository, times(1)).findAll(); verify(recordRepository, never()).deleteAll(anyList()); } }
2. 模拟多批数据删除场景
如果需要测试多次批量删除(比如先删2条、再删1条、最后无数据),只需继续链式添加thenReturn():
when(recordRepository.findAll()) .thenReturn(List.of(new Record(), new Record())) // 第一次删2条 .thenReturn(List.of(new Record())) // 第二次删1条 .thenReturn(Collections.emptyList()); // 第三次无数据,循环终止
关键说明
- 链式
thenReturn()的顺序严格对应方法调用次数,第一次调用取第一个返回值,第二次取第二个,以此类推。 - 通过
verify()可以验证Repository方法的调用次数,确保循环执行次数符合预期,同时覆盖两个核心代码分支:- 有数据时执行删除逻辑
- 无数据时触发
break退出循环
内容的提问来源于stack exchange,提问作者Anil Nivargi
相关产品推荐
相关产品推荐

