Spring Boot Assert错误:在使用MockMVC的Sping Boot 控制器单元测试中,JSON路径“$.title”处没有值

4dc9hkyq  于 2023-08-04  发布在  Spring
关注(0)|答案(1)|浏览(149)

我正在单元测试一个控制器方法来执行get请求。然而,我面临着jsonPath无法检索我正在测试的特定字段的困难,这是我的Content实体的“title”。getContent()方法本身工作正常,我不确定如何使用jsonPath来指示我需要的信息。
我正在测试的控制器方法:

@GetMapping("/{id}")
    public ResponseEntity<ContentDTO> getContent(@PathVariable
                                                 @Min(value = 1,
                                                      message = "{content.id.invalid}")
                                                      Integer id) throws ContentNotFoundException {
        Content content = contentService.getContent(id);
        return new ResponseEntity<ContentDTO>(contentMapper.entityToDTO(content), HttpStatus.OK);
    }

字符串
Controller方法的单元测试:

@WebMvcTest
public class ContentControllerTest {

    @MockBean //if a testcase is dependent on Spring container Bean then use this method
    private ContentService contentService;

    @MockBean
    private ContentMapper contentMapper;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    private Content content;
    private Content content2;

    @BeforeEach
    void init(){
        content = new Content();
        content.setId(1);
        content.setTitle("test content title name");
        content.setDesc("test content description for a new content");
        content.setStatus(Status.PUBLISHED);
        content.setContentType(Type.ARTICLE);
        content.setDateCreated(LocalDateTime.now());
        content.setUrl("http://test.com");

        content2 = new Content();
        content2.setId(2);
        content2.setTitle("test content title name2");
        content2.setDesc("test content description for a new content2");
        content2.setStatus(Status.PUBLISHED);
        content2.setContentType(Type.ARTICLE);
        content2.setDateCreated(LocalDateTime.now());
        content2.setUrl("http://test2.com");
    }

    @Test
    void getContentValidTest() throws Exception { //TEST THAT IS FAILING
        //given

        //when
        Mockito.when(contentService.getContent(content.getId()))
                .thenReturn(content);

        ResultActions response = mockMvc
                .perform(get("/api/content/{id}", content.getId())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(content)));

        //then
        response.andExpect(status().isOk())
                .andExpect(jsonPath("$.title")
                        .value(content.getTitle()));

    }


我收到的错误:

java.lang.AssertionError: No value at JSON path "$.title"


附加MockHttpServletRequest消息:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /api/content/1
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"226"]
             Body = {"id":1,"title":"test content title name","desc":"test content description for a new content","status":"PUBLISHED","contentType":"ARTICLE","dateCreated":"2023-07-26T17:14:50.8809845","dateUpdated":null,"url":"http://test.com"}
    Session Attrs = {}

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []


成功的 Postman 响应示例:

{
    "title": "My Spring Data Blog Post",
    "desc": "A post about spring data",
    "status": "IDEA",
    "contentType": "ARTICLE",
    "dateCreated": "2023-06-17T22:39:52",
    "dateUpdated": null,
    "url": null
}

blmhpbnm

blmhpbnm1#

如果查看MockHttpServletResponse的主体,您会注意到它是空的。这意味着控制器方法返回了一个空的主体作为响应。响应正文是contentMapper.entityToDTO(content)的结果。
但是在这种情况下,contentMapper.entityToDTO(content)返回null,因为contentMapper在测试中被@MockBean模拟,并且没有为它定义任何行为。
由于ContentMapper似乎属于控制器,因此我也会在测试中使用真实的实现,而不是模拟的实现。为此,您必须移除字段

@MockBean
private ContentMapper contentMapper;

字符串
并将一个@Import注解添加到测试类:

@WebMvcTest
@Import(ContentMapper.class)
public class ContentControllerTest {


我还注意到,在

mockMvc
    .perform(get("/api/content/{id}", content.getId())
        .contentType(MediaType.APPLICATION_JSON)
        .content(objectMapper.writeValueAsString(content)))


最后两行对于这个测试来说是不必要的,因为GET请求不需要也不应该有请求体。

相关问题