【发布时间】:2021-08-04 15:27:58
【问题描述】:
如下函数:
private Boolean canDoIt(Parameter param) {
return myService
.getMyObjectInReactiveWay(param)
.map(myObject -> myService.checkMyObjectInImperativeWay(myObject))
.block();
}
在运行时工作正常,但是在使用 WebTestClient 测试使用它的流时,我收到以下错误:
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread parallel-1
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83) ~[reactor-core-3.4.1.jar:3.4.1]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.MonoFlatMap] :
reactor.core.publisher.Mono.flatMap
我知道我不应该使用block(),但我别无选择:该函数必须返回Boolean(而不是Mono<Boolean>)。也许有另一种不使用block()的编写方式。
有没有办法让WebTestClient 不抛出该错误?
使用 Reactor Core 版本3.4.6。
【问题讨论】:
-
问题是 Reactor 实际上禁止在未明确标记为与阻塞代码兼容的调度程序中调用
block。我没有找到详细的文档,但我认为。在块调用之前,您必须在通量上使用subscribeOn(Schedulers.boundedElastic())或.share()方法。行为上的差异可能来自这样一个事实,在一种情况下,块函数在当前线程(非反应调度程序)中触发管道,但在您的测试中,您尝试从反应堆栈调用canDoIt,因此执行线程来自一个反应式调度程序。 -
我用
subscribeOn和share都试过了,但我仍然得到同样的错误。请注意,WebClient不会出现错误,它只会出现在WebTestClient。 -
也许我错过/误解了一些东西。您可以尝试使用 share 和 subscribeOn 进行编辑吗?此外,使用 WebTestClient 和
flatMap的失败代码会很好。这将有助于我进一步挖掘并调整我的答案。 -
另外,我做了一个相当通用的答案,因为我不太确定,但如果我有失败的代码(好吧,一个最小的可重现示例),我将能够制作一个答案真正专注于您的用例。
标签: java reactive-programming spring-webflux project-reactor webtestclient