java - Project Reactor - 使用 defer() 使方法可重试

标签 java reactive-programming project-reactor

最近,我尝试通过设置模拟依赖项来测试单元测试中的重试行为,以在最后返回成功的 mono.just() 之前返回多个 Mono.error() :

@Mock
Dependency dependency;

@InjectMocks
ClassUnderTest classUnderTest;

@Test
void someTest() {
    final Object object = new Object();
    when(dependency.method(anyString()))
        .thenReturn(Mono.error(new Exception()))
        .thenReturn(Mono.error(new Exception()))
        .thenReturn(Mono.error(new Exception()))
        .thenReturn(Mono.just(object));

    StepVerifier.create(classUnderTest.method("abc"))
        .expectNext(object)
        .verifyComplete();

    verify(dependency, times(4)).method("abc");
}

上面的设置不起作用,正如我后来发现的,Reactor中的重试不是通过在特定时间内调用该方法来完成的,而是通过调用该方法一次,获取发布者,然后重新订阅它一次又一次。

class ClassUnderTest {
    private Dependency dependency;

    public Mono<Object> method(final String str) {
        return this.dependency.method(str).retryWhen(Retry.max(3));
    }
}

如果 Dependency#method 实现为:

,则重新订阅不会起作用:

class Dependency {
    private OtherDependency otherDependency;

    public Mono<Object> method(final String str) {
        return this.otherDependency.get(str).map(/* some mapping logic */);
    }
}

Dependency#method 无法对 OtherDependency#get 是否延迟做出太多假设。因此,依赖需要:

class Dependency {
    private OtherDependency otherDependency;

    public Mono<Object> method(final String str) {
        return Mono.defer(() -> this.otherDependency.get(str)).map(/* some mapping logic */);
    }
}

既然我们想说每个方法都应该是“可重试的”,这是否意味着我们需要始终使用defer(...)

或者我误解了什么?

最佳答案

我应该考虑一下。

更简单的方法不是让所有方法本身“可重试”,而是在附加 retryWhen 运算符之前用 defer 包装发布者。

之前:

class ClassUnderTest {
    private Dependency dependency;

    public Mono<Object> method(final String str) {
        return dependency.method(str).retryWhen(Retry.max(3));
    }
}

之后:

class ClassUnderTest {
    private Dependency dependency;

    public Mono<Object> method(final String str) {
        return Mono.defer(() -> dependency.method(str)).retryWhen(Retry.max(3));
    }
}

现在,我们不必说所有方法都应该是 native “可重试的”,而是始终用 defer 包装要重试的发布者。

关于java - Project Reactor - 使用 defer() 使方法可重试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61466034/

相关文章:

java - 我们如何从 fragment 启动 Activity

java - Youtube Player API 导致 java.lang.NoClassDefFoundError

spring - 有没有办法打印出 Flux 中所有操作的链条?

python-3.x - 如何使用 rxpy/rxjs 延迟事件发射?

java - 使用 Project Reactor 并行调用其余 Web 服务?

java - new 运算符和 Class.newInstance() 有什么区别?

java - IntelliJ 无法识别 PATH 变量

javascript - 从 ORM 返回的一系列 Promise 生成一个 RxJS Observable

java - 通过 SSE 订阅的 Flux 引发 cancel() 事件

java - Project Reactor 将发布者一分为二,至少有两个订阅者