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

问题描述 投票:0回答:1

我正在对控制器方法进行单元测试以执行获取请求。但是,我面临着 jsonPath 无法检索我正在测试的特定字段(即我的内容实体的“标题”)的困难。

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);
    }

控制器方法的单元测试:

@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 = []

邮递员成功回复的示例:

{
    "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
}
java spring-boot unit-testing controller mocking
1个回答
0
投票

如果您查看 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 请求不需要也不应该有请求正文。

© www.soinside.com 2019 - 2024. All rights reserved.