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

响应式编程中OnErrorResume功能的JUnit测试方案咨询

响应式WebClient错误场景的JUnit测试解决方案

问题根源

你当前测试的核心问题是:用doThrow让myWebClient.getResponse()直接抛出异常,但响应式方法的设计是返回包含错误信号的Mono,而非直接抛出异常。这种直接抛出的异常会在赋值responseDataMono时就中断执行,根本无法进入后续的onErrorResume错误处理逻辑。

正确测试方案

1. 模拟WebClient返回带错误的Mono

不要用doThrow,而是让getResponse返回一个包含目标异常的Mono.error(),这样才能让响应式流正常流转到onErrorResume。

2. 触发响应式流执行

响应式流是惰性的,仅仅调用myServiceMethod()获取Mono不会执行任何逻辑,必须调用block()或者subscribe()来触发流的执行。

3. 验证错误处理逻辑

可以通过Mockito的参数捕获器、行为验证,或者断言最终结果来确认错误处理逻辑是否被正确触发。

修改后的测试代码

@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
    @InjectMocks
    private MyService myServiceMock;

    @Mock
    private MyWebClient myWebClient;

    @Test // 必须添加@Test注解,否则测试不会被执行
    public void testErrorCode400() {
        // 模拟WebClient返回包含400异常的Mono
        when(myWebClient.getResponse(anyString()))
                .thenReturn(Mono.error(new WebClientResponseException(400, "Bad Request", null, null, null)));

        // 触发响应式流执行
        Mono<Student> resultMono = myServiceMock.myServiceMethod();
        Student result = resultMono.block(); // block()会触发流执行并等待结果

        // 验证结果:因为onErrorResume返回Mono.empty(),所以block()会得到null
        Assert.assertNull(result);

        // 如果需要验证错误处理逻辑中的特定行为(比如日志、其他方法调用),可以用verify
        // 示例:verify(logger).error(anyString(), any(WebClientResponseException.class));
    }

    @Test
    public void testTimeoutException() {
        // 模拟超时异常场景
        when(myWebClient.getResponse(anyString()))
                .thenReturn(Mono.error(new io.netty.handler.timeout.TimeoutException()));

        Mono<Student> resultMono = myServiceMock.myServiceMethod();
        Student result = resultMono.block();

        Assert.assertNull(result);
        // 可在此添加超时错误逻辑的验证代码
    }
}

服务代码优化建议(可选)

你的服务代码可以简化冗余判断,去掉不必要的强转和冗余操作:

// 假设MyWebClient.getResponse返回的就是Mono<Student>,无需强转
Mono<Student> responseDataMono = myWebClient.getResponse("url");

return responseDataMono
        .onErrorResume(ex -> {
            if (ex instanceof WebClientResponseException webEx) {
                if (webEx.getStatusCode() == HttpStatus.NOT_FOUND) {
                    // 404处理逻辑
                } else if (webEx.getStatusCode() == HttpStatus.BAD_REQUEST) {
                    // 400处理逻辑
                }
            } else if (ex instanceof io.netty.handler.timeout.TimeoutException) {
                // 超时处理逻辑
            } else {
                // 其他错误处理逻辑
            }
            return Mono.empty();
        });
// 原代码中的map(resp -> resp)是冗余操作,可直接移除

内容的提问来源于stack exchange,提问作者Sweety

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:05:26