Reactor StepVerifier 测试因 blockFirst() 失败

问题描述 投票:0回答:2

这是检查数据库中重复名称的代码

public Mono<Void> validateDuplicateName(String name) throws RuntimeException {
    Flux<Customer> customerFlux = customerRepository.findByNameIgnoreCase(name);

    customerFlux.take(1).flatMap( customer -> {
        return Mono.error( new RuntimeException ("ABC99") );
    }).blockFirst();

    return Mono.empty();
}

下面是测试 validateDuplicateName 方法的测试脚本

when(customerRepositoryMocked.findByNameIgnoreCase(Mockito.anyString())).thenReturn(Flux.just(customerMocked));
StepVerifier.create(customerValidator.validateDuplicateName(Mockito.anyString()))
        .expectErrorMatches( exception -> exception instanceof RuntimeException )
        .verify();

但是测试失败并出现以下错误

java.lang.RuntimeException: ABC99
..
..
Suppressed: java.lang.Exception: #block terminated with an error
        at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:93)
        at reactor.core.publisher.Flux.blockFirst(Flux.java:2013)
        ... 34 more

我可以寻求帮助吗?

project-reactor
2个回答
0
投票

你的

StepVerifier
实际上只能测试方法系统返回的
Mono.empty()
。同时,您使用
blockFirst
,这将引发发布者发出的任何异常,从而使整个断言短路。

记住

StepVerifier
可以让您断言序列将异步发出您期望的内容(包括错误,以
onError
信号的形式)。如果序列甚至无法创建,因为创建它的方法 (
validateDuplicateName
) 会抛出异常,那么
StepVerifier
就无能为力了。

但真正的问题是 你到底为什么要阻塞一个具有

Mono
返回类型并且具有完美的
Mono
方便源的方法?
你的返回
Mono
必须源自该
customerFlux

您可以使用

then()
切换到
Mono<Void>
:这会忽略源元素,但会正确传播错误。


0
投票

如果您的 if

. blockFirst()
. block()
是不可避免的,并且您可能仍然想让 StepVerifier 在没有
Suppressed: java.lang.Exception: #block terminated with an error
的情况下成功,那么请将
. blockFirst()
. block()
替换为
.subscribe()

更改自:

public Mono<Void> validateDuplicateName(String name) throws RuntimeException {
    Flux<Customer> customerFlux = customerRepository.findByNameIgnoreCase(name);

    customerFlux.take(1).flatMap( customer -> {
        return Mono.error( new RuntimeException ("ABC99") );
    }).blockFirst();

    return Mono.empty();
}

更改为:

public Mono<Void> validateDuplicateName(String name) throws RuntimeException {
    Flux<Customer> customerFlux = customerRepository.findByNameIgnoreCase(name);

    customerFlux.take(1).flatMap( customer -> {
        return Mono.error( new RuntimeException ("ABC99") );
    }).subscribe();

    return Mono.empty();
}

一般来说,当

StepVerifier
失败并出现空
bodyToMono
onStatus
-->
HttpStatusCode::isError
导致空
bodyToMono
当错误没有设置正文时,
.block()
将导致

Suppressed: java.lang.Exception: #block terminated with an error

.block()
更改为
.subscribe()
后,我们可以放弃此错误并根据需要验证测试结果。

© www.soinside.com 2019 - 2024. All rights reserved.