代码之家  ›  专栏  ›  技术社区  ›  Hantsy

@WebfluxTest使用子资源失败,例如帖子/帖子id/评论

  •  1
  • Hantsy  · 技术社区  · 6 年前

    当我使用 @WebFluxTest 在模拟环境中测试我的控制器,并尝试 Comment 子资源 Post 又称作 /帖子/1/评论 ,失败。但是 /职位 相关端点工作。

    PostController 代码如下所示,完整的代码为 here :

    @RestController()
    @RequestMapping(value = "/posts")
    class PostController {
    
        private final PostRepository posts;
    
        private final CommentRepository comments;
    
        public PostController(PostRepository posts, CommentRepository comments) {
            this.posts = posts;
            this.comments = comments;
        }
    
        //other methods for /posts endpoints
    
        @GetMapping("/{id}/comments")
        public Flux<Comment> getCommentsOf(@PathVariable("id") String id) {
            return this.comments.findByPost(new PostId(id));
        }
    
        @PostMapping("/{id}/comments")
        public Mono<Comment> createCommentsOf(@PathVariable("id") String id, @RequestBody @Valid CommentForm form) {
            Comment comment = Comment.builder()
                .post(new PostId(id))
                .content(form.getContent())
                .build();
    
            return this.comments.save(comment);
        }
    
    }
    

    PostControllerTests 如下所示,完整代码为 here :

    @RunWith(SpringRunner.class)
    @WebFluxTest(controllers = PostController.class)
    public class PostControllerTest {
    
        @Autowired
        WebTestClient client;
    
        @MockBean
        PostRepository posts;
    
        @MockBean
        CommentRepository comments;
        // other tests
        @Test
        public void getCommentsByPostId_shouldBeOk() {
            given(comments.findByPost(new PostId("1")))
                .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);
    
        }
    
        @Test
        public void createCommentOfPost_shouldBeOk() {
    
            Comment comment = Comment.builder().id("comment-id-1").content("content of my first post").createdDate(LocalDateTime.now()).build();
            given(comments.save(comment))
                .willReturn(Mono.just(comment));
    
            CommentForm form = CommentForm.builder().content("comment of my first post").build();
            client.post().uri("/posts/1/comments").body(BodyInserters.fromObject(form))
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$.id").isEqualTo("comment-id-1")
                .jsonPath("$.content").isEqualTo("content of my first post")
                .jsonPath("$.createdDate").isNotEmpty();
    
            verify(this.comments, times(1)).save(any(Comment.class));
            verifyNoMoreInteractions(this.comments);
        }
    
    }
    

    当我跑的时候 getCommentsByPostId_shouldBeOk 测试,并获得异常:

    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
    

    我已经试过了 卷曲 ,还写道 integration tests for it ,它起作用了。

    已更新 :当我更改测试时 getCommentsByPostId\u应该确定 以下内容:

    EntityExchangeResult<byte[]>  results = client.get().uri("/posts/1/comments").exchange()
            .expectStatus().isOk()
            .expectBody().returnResult();
    
    log.debug("return results::" + new String(results.getResponseBody()));
    

    它打印了一个空json数组:

    2018-01-07 11:42:52.385 DEBUG 17492 --- [           main] com.example.demo.PostControllerTest      : return results::[]
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Oleh Dokuka    6 年前

    原因

    问题出在你的mockito mock准备中

    given(comments.findByPost(new PostId("1")))
            .willReturn(Flux.just(...));
    

    另外,请注意,在您的情况下 PostId #equals #hashcode 格式不正确,所以 new PostId("1").eqauls(new PostId("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 到您的 已发布 类,以便当前代码正常工作