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

单元测试时MainClass中flatMap绑定的add方法未触发调用排查

问题:WebClient异步流中flatMap指定的add方法未执行

业务代码

@Service
class MainClass {
public void simpleExe() {
webclient.post()
.uri("url")
.header(----)
.bodyValue(ReqPojo)
.retrieve()
.bodyToMono(Response.class)
.flatMap(this::add); // 该行已执行但add方法未被调用
}

private Mono<Response> add() {
// 执行一些计算逻辑
}
}

测试代码

@SpringBootTest
class MainClassTest {

// 已Mock部分其他服务调用

@Autowired
MainClass mainClass;
@Test
public void testsimpleExe() {
   mainClass.simpleExe();
 }
}

原因分析及解决方案

1. Reactor冷流未订阅(核心原因)

Reactor的Mono/Flux是冷流,只有调用subscribe()或者触发订阅操作(比如block())时,整个流才会真正执行。当前simpleExe方法只构建了流的链路,但没有触发订阅,所以flatMap里的add永远不会执行。

修复方案:

  • 修改simpleExe方法,返回整个流让调用方处理:
public Mono<Void> simpleExe() {
    return webclient.post()
        .uri("url")
        .header(----)
        .bodyValue(ReqPojo)
        .retrieve()
        .bodyToMono(Response.class)
        .flatMap(this::add)
        .then(); // 转为Mono<Void>标识流执行完成
}
  • 测试时触发订阅,推荐用StepVerifier验证流:
@Test
public void testsimpleExe() {
    StepVerifier.create(mainClass.simpleExe())
        .verifyComplete();
    
    // 测试环境下也可以直接用block()等待完成:
    // mainClass.simpleExe().block();
}

2. add方法签名不匹配

flatMap需要接收一个Function<Response, Mono<?>>类型的参数,也就是方法必须接收Response对象作为输入。但当前add方法是无参的,方法引用this::add不匹配flatMap的要求,自然无法正确触发调用。

修复方案:
修正add方法的签名,添加Response参数:

private Mono<Response> add(Response response) {
    // 执行计算逻辑
}

3. WebClient Mock不完整

如果WebClient没有正确Mock,导致bodyToMono(Response.class)返回Mono.empty()或错误流,flatMap不会处理空值,add方法也不会被触发。

修复方案:
确保Mock的WebClient返回正常的Mono<Response>,比如链式Mock调用链路:

@MockBean
private WebClient webClient;

@BeforeEach
void setUp() {
    WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class);
    WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class);
    WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class);

    when(webClient.post()).thenReturn(requestBodyUriSpec);
    when(requestBodyUriSpec.uri("url")).thenReturn(requestBodyUriSpec);
    when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec);
    when(requestBodyUriSpec.bodyValue(any(ReqPojo.class))).thenReturn(requestHeadersSpec);
    when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
    when(responseSpec.bodyToMono(Response.class)).thenReturn(Mono.just(new Response()));
}

4. 测试未等待异步操作完成

测试方法调用mainClass.simpleExe()后会直接结束,JUnit会终止线程,导致异步流还没执行到flatMap就被中断,看起来add没被调用。

修复方案:
参考第1点的测试代码,用StepVerifier或者block()等待流执行完成。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:01:55