Spring @WebfluxTest使用子资源失败,例如posts/post id/comments

Spring @WebfluxTest使用子资源失败,例如posts/post id/comments,spring,spring-test,project-reactor,spring-webflux,spring-boot-test,Spring,Spring Test,Project Reactor,Spring Webflux,Spring Boot Test,当我使用@WebFluxTest在模拟环境中测试我的控制器,并尝试测试Postaka/posts/1/comments的Comment子资源时,失败。但是对/posts相关端点的测试是有效的 PostController代码如下,完整的代码如下: 当我运行getCommentsByPostId\u应该是OKtest时,出现异常: java.lang.AssertionError: No value at JSON path "$[0].id" at org.springframework.te

当我使用
@WebFluxTest
在模拟环境中测试我的控制器,并尝试测试
Post
aka/posts/1/comments
Comment
子资源时,失败。但是对/posts相关端点的测试是有效的

PostController
代码如下,完整的代码如下:

当我运行
getCommentsByPostId\u应该是OK
test时,出现异常:

java.lang.AssertionError: No value at JSON path "$[0].id"

at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:247)
at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:100)
at org.springframework.test.web.reactive.server.JsonPathAssertions.isEqualTo(JsonPathAssertions.java:49)
at com.example.demo.PostControllerTest.getCommentsByPostId_shouldBeOk(PostControllerTest.java:198)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: com.jayway.jsonpath.PathNotFoundException: No results for path: $[0]['id']
at com.jayway.jsonpath.internal.path.EvaluationContextImpl.getValue(EvaluationContextImpl.java:133)
at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)
at com.jayway.jsonpath.JsonPath.read(JsonPath.java:345)
at com.jayway.jsonpath.JsonPath.read(JsonPath.java:329)
at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:244)
... 33 more
我尝试了curl的评论endpionts,还写了一篇文章,它很有效

更新:当我将测试
getCommentsByPostId_应确定
更改为以下内容时:

EntityExchangeResult<byte[]>  results = client.get().uri("/posts/1/comments").exchange()
        .expectStatus().isOk()
        .expectBody().returnResult();

log.debug("return results::" + new String(results.getResponseBody()));
原因 问题在于你的模拟准备

given(comments.findByPost(new PostId("1")))
        .willReturn(Flux.just(...));
另外,请注意,在您的情况下,
PostId
#equals
#hashcode
格式不正确,因此
newpostid(“1”).eqauls(newpostid(“1”)
返回
false

修复 试着用下一种方法来修正你的mockito准备,然后所有的期望都会被通过

 given(comments.findByPost(any()))
            .willReturn(Flux.just(Comment.builder().id("comment-id-1").content("comment of my first post").build()));

        client.get()
              .uri("/posts/1/comments")
              .exchange()
              .expectStatus().isOk()
              .expectBody()
              .jsonPath("$[0].id").isEqualTo("comment-id-1")
              .jsonPath("$[0].content").isEqualTo("comment of my first post");

        verify(this.comments, times(1)).findByPost(any(PostId.class));
        verifyNoMoreInteractions(this.comments);

将注解
@EqualsAndHashCode
添加到你的
posted
类中,这样你当前的代码就可以工作了

@Hantsy,我已经为你的repose创建了一个PR谢谢。但是为什么我需要在给定语句中传递一个
any
,而不是一个实参数呢?在此之前的测试类中的所有测试都运行良好。我在Prefore项目中也这样使用了Mockito。@Hantsy,实际上,您的
PostId
格式不正确,因为,
newpostid(“1”).equals(newpostid(“1”)
返回
false
。这就是为什么given(……(newpostid(“1”)永远不会用它来调用的原因parameter@Hatnsy,您错过了
@EqualsAndHashCode
注释谢谢您的解释。
2018-01-07 11:42:52.385 DEBUG 17492 --- [           main] com.example.demo.PostControllerTest      : return results::[]
given(comments.findByPost(new PostId("1")))
        .willReturn(Flux.just(...));
 given(comments.findByPost(any()))
            .willReturn(Flux.just(Comment.builder().id("comment-id-1").content("comment of my first post").build()));

        client.get()
              .uri("/posts/1/comments")
              .exchange()
              .expectStatus().isOk()
              .expectBody()
              .jsonPath("$[0].id").isEqualTo("comment-id-1")
              .jsonPath("$[0].content").isEqualTo("comment of my first post");

        verify(this.comments, times(1)).findByPost(any(PostId.class));
        verifyNoMoreInteractions(this.comments);