[英]Mock services in Spring Reactor
让我们看一下这个简单的方法:
public Mono<SuccessResponse> doSomething(){
return service1.doSomething()
.then(service2.doSomething2())
.thenReturn(new SuccessResponse("Awesome")));
}
因此,基本上,我想针对其中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!?
我的问题是为什么service2.doSomething()被执行一次? 它不应该执行,因为service1.doSomething()在上面抛出错误...
调用service2.doSomething()
方法的原因是,虽然Mono
可以是惰性的,但不能简单地调用运算符。 您急切地调用将返回惰性Mono
的方法,从而组装了处理管道。
如果您内联代码,我认为它会变得更加清晰:
//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")));
一些操作员接受“ Supplier
或“ Function
,这是这种急切的构造样式的一种替代方案。 一种通用的方式是使用Mono.defer
:
public Mono<SuccessResponse> doSomething(){
return service1.doSomething()
.then(Mono.defer(service2::doSomething2))
.thenReturn(new SuccessResponse("Awesome")));
}
但是我认为 , 除非service2
隐藏了一个不是惰性的源(例如,从CompletableFuture
改编的Mono
) , 否则问题不是doSomething
而是测试 。
使用service2
模拟,您实际上是在测试运算符链的组装,但是如果管道中的该步骤实际上已执行,则不会进行测试。
reactor-test
可用的一个技巧是将Mono.just
/ Mono.error
包装在PublisherProbe
。 它可以像您一样模拟Mono
,但是具有在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();
thenReturn
不是因为抛出错误! 您需要使用thenThrow()
并且也不需要为service2编写模拟方法,只需验证已调用了
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.