我有一个像这样的简单存储库实现。
@Repository
public interface PolicyRepository extends ReactiveMongoRepository<Policy, String> {
@Query("{ id: { $exists: true }}")
Flux<Policy> findAllPaged(Pageable pageable);
@Query("{ name: { $eq: ?0 }}")
Mono<Policy> findByName(String name);
}
在这样的控制器上还有一个简单的动作方法。
@ResponseStatus(HttpStatus.CREATED)
public Mono<ResponseEntity<String>> createPolicy(@Valid @RequestBody Policy policy) {
//Use The Mongodb ID Generator
policy.setId(ObjectId.get().toString());
return policyRepository.findByName(policy.getName()).flatMap(policy1 -> {
return Mono.just(ResponseEntity.badRequest().body("A Policy with the same name as the policy you are trying to create" +
"already exists"));
}).switchIfEmpty(
policyRepository.save(policy).map(p2 ->{
eventPublisher.publish(Events.POLICY_CREATED, p2.getId());
return ResponseEntity.status(HttpStatus.CREATED).body("Policy definition created successfully");
}));
}
我要实现的目标是,如果存在与插入的策略同名的策略,则返回错误请求;如果findByName方法返回空,则执行保存操作。
奇怪的行为是以下测试失败,因为无论findByName是否返回数据,总是调用save。
这是测试
@Test
void testCreateDuplicatePolicyShouldFail() {
given(policyRepository.findByName(eq(policy.getName()))).willReturn(Mono.just(policy));
given(policyRepository.save(any(Policy.class))).willReturn(Mono.just(policy));
given(eventPublisher.publish(Events.POLICY_CREATED, policy.getId())).willReturn(Mono.just(0L));
webTestClient.post().uri("/policies")
.syncBody(policy)
.exchange()
.expectStatus().isBadRequest();
verify(policyRepository, times(1)).findByName(eq(policy.getName()));
verify(policyRepository, times(0)).save(any(Policy.class));
verify(eventPublisher, times(0)).publish(Events.POLICY_CREATED, policy.getId());
}
它失败,并出现以下异常
org.mockito.exceptions.verification.NeverWantedButInvoked:
com.management.dashboard.repository.PolicyRepository#0 bean.save(
<any com.management.core.model.Policy>
);
请问我做错了什么。任何指针将不胜感激。
答案 0 :(得分:1)
能否请您确认在测试中您正在设置一个空的单声道。
请您替换下面的行:
given(policyRepository.findByName(eq(policy.getName()))).willReturn(Mono.just(policy));
此行:
given(policyRepository.findByName(eq(policy.getName()))).willReturn(Mono.empty());
仅当流为空时才调用switchIfEmpty运算符。 此外,您还可以启用日志来跟踪流。这可以通过在switchIfEmpty之后添加一个日志运算符来完成。例如
return policyRepository.findByName()
.switchIfEmpty()
.log();
答案 1 :(得分:1)
我遇到了同样的错误,解决方法是使用Mono.defer(()->...)
函数中的.switchIfEmpty()
,根据此medium的文章,如果期望开关总是执行而不会产生副作用,
答案 2 :(得分:0)
该模拟设置的问题是始终save()
被调用。实际存储库返回的Mono
是惰性的,因此在订阅之前没有任何反应。 switchIfEmpty
的工作是仅在没有收到onNext
信号的情况下进行所述订阅。
方法调用就是方法调用。 switchIfEmpty
无法阻止save
以这种形式执行。好像您有System.out.println(getMessage())
之类的东西:getMessage
会在执行整行时被调用;)
要进行测试,您可以在模拟中使用reactor-test
的{{1}}:
PublisherProbe