You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 19:52:07