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

如何验证Project Reactor中retryWhen的方法调用次数?

问题根源

响应式流(Reactor Mono)是异步执行的,你的测试方法在revertChange()返回的Mono还没完成全部重试逻辑时,就执行了verify校验,因此只能捕获到第一次方法调用。

适配响应式Mock的解决方案(JUnit 5 + JMockit)

核心思路是确保测试等待响应式流完全执行完毕,再进行调用次数验证,同时正确Mock服务方法触发重试逻辑。

步骤1:正确Mock服务方法,触发重试

让someService.someMethod()每次调用都抛出你指定的触发重试的异常,这样retryWhen逻辑才会生效。

步骤2:等待响应式流完成

使用Reactor官方提供的StepVerifier(推荐)或调用block()方法,确保Mono的所有重试步骤执行完毕。

步骤3:用JMockit验证调用次数

在流完成后,通过JMockit的Verifications或Expectations校验方法调用次数。

完整测试代码示例

@ExtendWith(JMockitExtension.class)
class YourTestClass {
    @InjectMocks
    private YourServiceClass underTest; // 包含revertChange方法的类
    @Mocked
    private SomeService someService;

    @Test
    void shouldCallSomeServiceExactlyThreeTimes_whenErrorOccurs() {
        // 1. Mock someMethod,每次调用抛出触发重试的特定异常
        new Expectations() {{
            someService.someMethod();
            result = new YourSpecificException(); // 替换为你的特定异常类型
        }};

        // 2. 执行目标方法,用StepVerifier等待流完成并验证最终结果
        Mono<Integer> resultMono = underTest.revertChange();
        StepVerifier.create(resultMono)
                .expectError(YourSpecificException.class) // 重试3次后最终抛出异常
                .verify();

        // 3. 验证someMethod被调用恰好3次
        new Verifications() {{
            someService.someMethod();
            times = 3;
        }};
    }
}

关键注意点

  • 不要忽略响应式流的异步特性:必须等待流终止后再做校验,否则重试逻辑还没执行就会触发verify,导致结果不符合预期。
  • StepVerifier是Reactor测试的标准工具:它不仅能等待流完成,还能验证流的元素、错误、完成信号等,比直接用block()更适合响应式场景。
  • JMockit的Expectations和Verifications:前者用于预先定义Mock行为,后者用于事后验证调用次数,两者配合使用可以准确覆盖重试场景的校验需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:05:23