如何验证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
相关产品推荐
相关产品推荐

