我正在使用Spring Data Reactive MongoDB存储库来非阻塞保存新的pojo。我的路由器功能是:
//other routes
.andRoute(POST("/article/json"), articleHandler::createArticle);
处理函数是:
public Mono<ServerResponse> createArticle(ServerRequest request) {
Flux<Article> article = request.bodyToFlux(Article.class);
articleRepository.insert(article).subscribe();
return ServerResponse.ok().build();
}
我的测试方法:
@Test
public void givenNewArticle_whenDataIsValid_thenSuccess() {
//create new article object
webTestClient.post()
.uri("/article/json")
.body(fromObject(article))
.exchange()
.expectStatus().isOk();
}
如果我通过curl发送json数据,应用程序工作正常。但是测试方法不起作用。并且日志中没有错误或任何插入文档事件:
2017-11-09 10:49:27.793 INFO 18224 --- [ Thread-4] org.mongodb.driver.connection : Opened connection [connectionId{localValue:6, serverValue:17563}] to 10.45.250.101:9017
2017-11-09 10:49:27.793 INFO 18224 --- [ Thread-5] org.mongodb.driver.connection : Opened connection [connectionId{localValue:5, serverValue:17562}] to 10.45.250.101:9017
2017-11-09 10:49:28.115 INFO 18224 --- [ Thread-11] .r.c.ReactiveWebServerApplicationContext : Closing org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext@4e423aa2: startup date [Thu Nov 09 10:49:23 MSK 2017]; root of context hierarchy
2017-11-09 10:49:28.117 DEBUG 18224 --- [ Thread-11] o.s.d.r.l.RedisMessageListenerContainer : Stopped RedisMessageListenerContainer
2017-11-09 10:49:28.127 INFO 18224 --- [ Thread-11] org.mongodb.driver.connection : Closed connection [connectionId{localValue:4, serverValue:17561}] to 10.45.250.101:9017 because the pool has been closed.
2017-11-09 10:49:28.128 INFO 18224 --- [ Thread-11] org.mongodb.driver.connection : Closed connection [connectionId{localValue:3, serverValue:17560}] to 10.45.250.101:9017 because the pool has been closed.
2017-11-09 10:49:28.129 INFO 18224 --- [ Thread-11] org.mongodb.driver.connection : Closed connection [connectionId{localValue:5, serverValue:17562}] to 10.45.250.101:9017 because the pool has been closed.
2017-11-09 10:49:28.129 INFO 18224 --- [ Thread-11] org.mongodb.driver.connection : Closed connection [connectionId{localValue:6, serverValue:17563}] to 10.45.250.101:9017 because the pool has been closed.
2017-11-09 10:49:28.132 INFO 18224 --- [ Thread-11] r.ipc.netty.tcp.BlockingNettyContext : Stopped HttpServer on /0:0:0:0:0:0:0:0:61441
通过WebTestClient测试restful api的正确方法是什么? TIA!
答案 0 :(得分:2)
你的测试工作正在暗示一个真正的错误。
一般规则:您不应该在返回被动类型的方法中调用subscribe
。您应该从头到尾构建一个被动管道。
在这种情况下,调用subscribe
将触发保存操作,但无法保证方法在完成后将返回。 subscribe
返回跟踪该操作完成(成功或错误)的Disposable
。保存该数据的实际工作可能发生在不同的线程中。
当使用curl手动完成时,这是有效的,因为在从服务器返回响应后,应用程序仍在运行。对于测试,应用程序在保存操作发生之前停止。保存操作尚未发生。
您可以通过以下方式“修复”此问题:
public Mono<ServerResponse> createArticle(ServerRequest request) {
Flux<Article> article = request.bodyToFlux(Article.class);
articleRepository.insert(article).subscribe().block();
return ServerResponse.ok().build();
}
但是通过此修复程序,您将在被动管道中间引入阻塞操作 - 这是一个严重的性能问题。这样做可能会阻塞服务器的几个线程并导致性能很差。
修复如下所示(分解超出要求的东西,你可以缩短它):
public Mono<ServerResponse> createArticle(ServerRequest request) {
Flux<Article> articles = request.bodyToFlux(Article.class);
Flux<Article> savedArticles = articleRepository.insert(articles);
return savedArticles.then(ServerResponse.ok().build());
}
此修复程序比以前的解决方案有两个优点:
onError*
Reactor运算符自定义事物)进入反应性思维模式并不明显,所以编写测试肯定是挑战你的假设的正确方法 - 你做了正确的调用。