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

为何含expectAccessibleContext的Reactor测试代码执行失败?

问题原因与解决方案

错误核心原因

  1. 关于flatMap未执行的误解:你描述的"flatMap从未执行"大概率不准确——Mono.just("Start")一定会发出元素,经过map转换为Optional.of("Start")后,defaultIfEmpty不会触发(因为上游有元素),所以flatMap必然会被执行。如果确实未执行,排查方向是map操作是否有未捕获的异常(但这里Optional.of("Start")不会抛异常)或OID的定义是否有误。

  2. 上下文断言失败的真正原因:
    第一个代码中,contextWrite被放在then()之后,而then()会忽略上游元素,仅返回一个Mono<Void>(仅发出onComplete信号)。虽然contextWrite修改了这个Mono<Void>的上下文,但map+defaultIfEmpty的链式调用会创建新的Mono实例,导致上下文传递链出现隐式隔离,StepVerifier无法捕获到onComplete信号携带的修改后上下文。
    而第二个代码中,flatMap直接作用在原始Mono上,没有额外的map+defaultIfEmpty环节,onComplete信号的上下文能被StepVerifier正常捕获,因此断言成功。

修复方案

方案1:调整contextWrite的位置

将contextWrite移到then()之前,确保上下文修改作用在带有元素的Mono上,then()返回的完成信号会继承这个上下文:

@Test
void name() {
    StepVerifier.create(Mono.just("Start")
                    .map(val -> Optional.of(val)).defaultIfEmpty(Optional.empty())
                    .flatMap(val -> Mono.just(val).contextWrite(ctx -> ctx.put(OID, "Hey")).then()))
            .expectAccessibleContext()
            .contains(OID, "Hey")
            .then()
            .verifyComplete();
}

方案2:替换then()为直接返回完成信号

如果不需要处理上游元素,直接返回一个带上下文的空完成信号,避免then()的隐式上下文传递问题:

@Test
void name() {
    StepVerifier.create(Mono.just("Start")
                    .map(val -> Optional.of(val)).defaultIfEmpty(Optional.empty())
                    .flatMap(val -> Mono.fromRunnable(() -> {}).contextWrite(ctx -> ctx.put(OID, "Hey"))))
            .expectAccessibleContext()
            .contains(OID, "Hey")
            .then()
            .verifyComplete();
}

修复逻辑说明

两种方案都确保了contextWrite修改的上下文能被传递到最终的onComplete信号中,StepVerifier的expectAccessibleContext就能捕获到带有OID的上下文,断言通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:34:53