bre*_*Dev 1 java mockito reactor spring-boot spring-webflux
让我们来看看这个简单的方法:
public Mono<SuccessResponse> doSomething(){
return service1.doSomething()
.then(service2.doSomething2())
.thenReturn(new SuccessResponse("Awesome")));
}
Run Code Online (Sandbox Code Playgroud)
所以基本上我想在 service1.doSomething() 会抛出错误的情况下测试这个方法:
when(service1.doSomething()).thenReturn(Mono.error(new IllegalStateException("Something bad happened")));
when(service2.doSomething()).thenReturn(Mono.just(new SomeResponse()))
assertThatThrownBy(() -> testedService.doSomething().block())
.isExactlyInstanceOf(IllegalStateException.class);
verify(service2, never()).doSomething(); //Why this is executed!?
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么 service2.doSomething() 被执行一次?它不应该被执行,因为 service1.doSomething() 在上面抛出一个错误......
service2.doSomething()调用该方法的原因是虽然 aMono可以是懒惰的,但简单地调用运算符却不是。您急切地调用将返回 lazyMono的方法,从而组装了一个处理管道。
如果您内联您的代码,我认为它会变得更加清晰:
//exception is CREATED immediately, but USED lazily
return Mono.error(new IllegalStateException())
//mono is CREATED immediately. The data it will emit is also CREATED immediately. But it all triggers LAZILY.
.then(Mono.just(new SomeResponse()))
//note that then* operators completely ignore previous step's result (unless it is an error)
.thenReturn(new SuccessResponse("Awesome")));
Run Code Online (Sandbox Code Playgroud)
一些运算符接受SupplierorFunction为这种急切的构造风格提供了一种懒惰的替代方案。一种通用的方法是使用Mono.defer:
public Mono<SuccessResponse> doSomething(){
return service1.doSomething()
.then(Mono.defer(service2::doSomething2))
.thenReturn(new SuccessResponse("Awesome")));
}
Run Code Online (Sandbox Code Playgroud)
但我认为,除非service2隐藏了一个不懒惰的源(例如,aMono改编自 a CompletableFuture),否则问题不doSomething在于 test。
使用service2模拟,您实际上是在测试运算符链的组装,但如果管道中的该步骤实际执行,则不会。
中可用的一个技巧reactor-test是将Mono.just/包装Mono.error在PublisherProbe. 这可以Mono像你一样用来模拟 a ,但增加了在执行时提供断言的功能Mono:它订阅了吗?被要求了吗?
//this is ultimately tested by the assertThrownBy, let's keep it that way:
when(service1.doSomething()).thenReturn(Mono.error(new IllegalStateException("Something bad happened")));
//this will be used to ensure the `service2` Mono is never actually used:
PublisherProbe<SomeResponse> service2Probe = PublisherProbe.of(Mono.just(new SomeResponse()));
//we still need the mock to return a Mono version of our probe
when(service2.doSomething()).thenReturn(service2Probe.mono());
assertThatThrownBy(() -> testedService.doSomething().block())
.isExactlyInstanceOf(IllegalStateException.class);
//service2 might have returned a lazy Mono, but it was never actually used:
probe.assertWasNotSubscribed();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3771 次 |
| 最近记录: |