单元测试时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
相关产品推荐
相关产品推荐

