如何使用Mockito模拟Do-While循环?
如何用Mockito模拟Do-While循环分页场景
先理清楚问题:你的业务方法getAllApplesByServer用do-while循环分页拉取苹果数据,直到某一页返回空列表才停止。要测试这个逻辑,得让Mockito模拟WebClient的多次调用——前几次返回有数据的页,最后一次返回空页,触发循环结束。
核心解决办法
Mockito支持给同一个方法调用设置连续返回值,用thenReturn(value1, value2)的写法就行:第一次调用返回value1,第二次返回value2,以此类推。对应到你的分页场景,就是让WebClient的bodyToFlux第一次返回带数据的Flux,第二次返回空Flux,这样collectList().block()就会先拿到非空列表,再拿到空列表,刚好触发do-while的退出条件。
修正后的测试代码
先把你原测试里的笔误改了(比如bodyToFlux(Strategy.class)应该是bodyToFlux(Apple.class),还有变量名拼写错误),然后写正确的模拟逻辑:
@Test void getAllApplesByServer_withPagination() throws SSLException { // 准备测试数据 Apple apple1 = new Apple(); apple1.setName("RedApple"); apple1.setEntityVersion("v1"); Apple apple2 = new Apple(); apple2.setName("GreenApple"); apple2.setEntityVersion("v1"); List<Apple> firstPage = Arrays.asList(apple1, apple2); List<Apple> emptyPage = Collections.emptyList(); // 模拟WebClient链式调用,设置连续返回值 when(webClientMock.get()).thenReturn(requestHeadersUriSpec); when(requestHeadersUriSpec.uri(anyString())).thenReturn(requestBodyMock); when(requestBodyMock.header(anyString(), anyString())).thenReturn(requestBodyMock); when(requestBodyMock.retrieve()).thenReturn(responseMock); // 第一次返回有数据的Flux,第二次返回空Flux when(responseMock.bodyToFlux(Apple.class)) .thenReturn(Flux.fromIterable(firstPage)) .thenReturn(Flux.empty()); // 执行测试方法 List<Apple> result = appleService.getAllApplesByServer("farm"); // 断言结果:合并了第一页的所有数据 assertEquals(2, result.size()); assertTrue(result.contains(apple1)); assertTrue(result.contains(apple2)); // 验证WebClient的get方法被调用2次(对应2页请求) verify(webClientMock, times(2)).get(); // 验证uri方法被调用2次 verify(requestHeadersUriSpec, times(2)).uri(anyString()); }
细节说明
- 连续返回值的作用:
thenReturn(Flux.fromIterable(firstPage)).thenReturn(Flux.empty())表示第一次调用bodyToFlux时返回2个Apple,第二次返回空,这样do-while循环会执行两次——第一次加数据,第二次拿到空列表,退出循环。 - 验证调用次数:用
verify(mock, times(n))确认分页请求次数对不对,这里循环跑了2次,所以WebClient的get方法得被调用2次。 - 笔误修正:原业务方法里
return allappleList是拼写错了,应该是return allAppleList;原测试里bodyToFlux(Strategy.class)类型不匹配,要改成Apple.class,不然会报错。
扩展:验证分页参数
如果你想确认每次请求的page参数是不是正确(比如第一次page=1,第二次page=2),可以用ArgumentCaptor捕获uri参数来检查:
// 定义捕获器抓uri字符串 ArgumentCaptor<String> uriCaptor = ArgumentCaptor.forClass(String.class); // 验证uri方法被调用2次,同时捕获参数 verify(requestHeadersUriSpec, times(2)).uri(uriCaptor.capture()); // 获取所有捕获的uri List<String> capturedUris = uriCaptor.getAllValues(); // 检查第一个uri带page=1,第二个带page=2 assertTrue(capturedUris.get(0).contains("page=1")); assertTrue(capturedUris.get(1).contains("page=2"));
内容的提问来源于stack exchange,提问作者Chaitanya
相关产品推荐
相关产品推荐

