How to check values in response body with mockMvc - AssertionError: Status expected:<201> but was:<400>
How to check values in response body with mockMvc - AssertionError: Status expected:<201> but was:<400>
我是测试写作的新手,我正在尝试使用 mockMvc 为我的控制器 class 编写 junit 测试。
这是我的 classes:
public class StudentDTO {
private final String firstName;
private final String lastName;
private final String JMBAG;
private final Integer numberOfECTS;
private final boolean tuitionShouldBePaid;}
命令class
public class StudentCommand {
@NotBlank (message = "First name must not be empty!")
private String firstName;
@NotBlank (message = "Last name must not be empty!")
private String lastName;
@NotNull(message = "Date of birth must be entered!")
@Past(message = "Date of birth must be in the past!")
private LocalDate dateOfBirth;
@NotBlank(message = "JMBAG must not be empty!")
@Pattern(message = "JMBAG must have 10 digits", regexp = "[\d]{10}")
private String jmbag;
@NotNull(message = "Number of ECTS points must be entered!")
@PositiveOrZero(message = "Number of ECTS points must be entered as a positive integer!")
private Integer numberOfECTS;}
控制器class:
@Secured({"ROLE_ADMIN"})
@PostMapping
public ResponseEntity<StudentDTO> save(@Valid @RequestBody final StudentCommand command){
return studentService.save(command)
.map(
studentDTO -> ResponseEntity
.status(HttpStatus.CREATED)
.body(studentDTO)
)
.orElseGet(
() -> ResponseEntity
.status(HttpStatus.CONFLICT)
.build()
);
}
测试class:
@SpringBootTest
@AutoConfigureMockMvc class StudentControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private StudentService studentServiceMock;
@Autowired
private ObjectMapper objectMapper;
private final String TEST_FIRST_NAME = "Marry";
private final String TEST_LAST_NAME = "Blinks";
private final String TEST_JMBAG = "0025478451";
private final Integer TEST_NUMBER_OF_ECTS = 55;
private final boolean TEST_TUITION_SHOULD_BE_PAID = true;
private final LocalDate TEST_DATE_OF_BIRTH = LocalDate.parse("1999-01-12");
@Test
void testSave() throws Exception {
StudentCommand studentCommand = new StudentCommand(TEST_FIRST_NAME,TEST_LAST_NAME,TEST_DATE_OF_BIRTH,TEST_JMBAG,TEST_NUMBER_OF_ECTS);
this.mockMvc.perform(
post("/student")
.with(user("admin")
.password("test")
.roles("ADMIN")
)
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(studentCommand))
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.jmbag").value(TEST_JMBAG))
.andExpect(jsonPath("$.firstName").value(TEST_FIRST_NAME))
.andExpect(jsonPath("$.lastName").value(TEST_LAST_NAME));
}
我总是因为这个错误而导致测试失败:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /student
Parameters = {_csrf=[30de7a8f-a3d5-429d-a778-beabd1a533da]}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"272"]
Body = {"firstName":"Marry","lastName":"Blinks","dateOfBirth":{"year":1999,"month":"JANUARY","monthValue":1,"dayOfMonth":12,"chronology":{"id":"ISO","calendarType":"iso8601"},"dayOfWeek":"TUESDAY","leapYear":false,"dayOfYear":12,"era":"CE"},"jmbag":"0025478451","numberOfECTS":55}
Session Attrs = {}
Handler:
Type = com.studapp.students.StudentController
Method = com.studapp.students.StudentController#save(StudentCommand)
MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<201> but was:<400>
Expected :201
Actual :400
我不确定为什么会失败。为什么响应正文是空白的?我不想调用我的服务,因为我没有测试它,但我觉得我应该以某种方式调用它(但话又说回来,我没有测试服务)。
如有任何建议,我们将不胜感激。
您应该在 ObjectMapper
上使用 @Autowired
以确保 Spring 以与应用程序运行时相同的方式对其进行配置。这将解释您收到的 400 - 错误请求错误。
自动装配 ObjectMapper
后出现 409 - 冲突这一事实表明这确实是错误所在。
由于您没有在测试中配置 studentServiceMock
,因此 409 似乎是来自控制器的适当答案,因为正在执行 orElseGet
部分。
如果我没记错的话,你可以把测试 class 注释精简一点,只使用 @WebMvcTest
。这种测试应该够用了,速度应该会快一点。
我是测试写作的新手,我正在尝试使用 mockMvc 为我的控制器 class 编写 junit 测试。
这是我的 classes:
public class StudentDTO {
private final String firstName;
private final String lastName;
private final String JMBAG;
private final Integer numberOfECTS;
private final boolean tuitionShouldBePaid;}
命令class
public class StudentCommand {
@NotBlank (message = "First name must not be empty!")
private String firstName;
@NotBlank (message = "Last name must not be empty!")
private String lastName;
@NotNull(message = "Date of birth must be entered!")
@Past(message = "Date of birth must be in the past!")
private LocalDate dateOfBirth;
@NotBlank(message = "JMBAG must not be empty!")
@Pattern(message = "JMBAG must have 10 digits", regexp = "[\d]{10}")
private String jmbag;
@NotNull(message = "Number of ECTS points must be entered!")
@PositiveOrZero(message = "Number of ECTS points must be entered as a positive integer!")
private Integer numberOfECTS;}
控制器class:
@Secured({"ROLE_ADMIN"})
@PostMapping
public ResponseEntity<StudentDTO> save(@Valid @RequestBody final StudentCommand command){
return studentService.save(command)
.map(
studentDTO -> ResponseEntity
.status(HttpStatus.CREATED)
.body(studentDTO)
)
.orElseGet(
() -> ResponseEntity
.status(HttpStatus.CONFLICT)
.build()
);
}
测试class:
@SpringBootTest
@AutoConfigureMockMvc class StudentControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private StudentService studentServiceMock;
@Autowired
private ObjectMapper objectMapper;
private final String TEST_FIRST_NAME = "Marry";
private final String TEST_LAST_NAME = "Blinks";
private final String TEST_JMBAG = "0025478451";
private final Integer TEST_NUMBER_OF_ECTS = 55;
private final boolean TEST_TUITION_SHOULD_BE_PAID = true;
private final LocalDate TEST_DATE_OF_BIRTH = LocalDate.parse("1999-01-12");
@Test
void testSave() throws Exception {
StudentCommand studentCommand = new StudentCommand(TEST_FIRST_NAME,TEST_LAST_NAME,TEST_DATE_OF_BIRTH,TEST_JMBAG,TEST_NUMBER_OF_ECTS);
this.mockMvc.perform(
post("/student")
.with(user("admin")
.password("test")
.roles("ADMIN")
)
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(studentCommand))
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.jmbag").value(TEST_JMBAG))
.andExpect(jsonPath("$.firstName").value(TEST_FIRST_NAME))
.andExpect(jsonPath("$.lastName").value(TEST_LAST_NAME));
}
我总是因为这个错误而导致测试失败:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /student
Parameters = {_csrf=[30de7a8f-a3d5-429d-a778-beabd1a533da]}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"272"]
Body = {"firstName":"Marry","lastName":"Blinks","dateOfBirth":{"year":1999,"month":"JANUARY","monthValue":1,"dayOfMonth":12,"chronology":{"id":"ISO","calendarType":"iso8601"},"dayOfWeek":"TUESDAY","leapYear":false,"dayOfYear":12,"era":"CE"},"jmbag":"0025478451","numberOfECTS":55}
Session Attrs = {}
Handler:
Type = com.studapp.students.StudentController
Method = com.studapp.students.StudentController#save(StudentCommand)
MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<201> but was:<400>
Expected :201
Actual :400
我不确定为什么会失败。为什么响应正文是空白的?我不想调用我的服务,因为我没有测试它,但我觉得我应该以某种方式调用它(但话又说回来,我没有测试服务)。 如有任何建议,我们将不胜感激。
您应该在 ObjectMapper
上使用 @Autowired
以确保 Spring 以与应用程序运行时相同的方式对其进行配置。这将解释您收到的 400 - 错误请求错误。
自动装配 ObjectMapper
后出现 409 - 冲突这一事实表明这确实是错误所在。
由于您没有在测试中配置 studentServiceMock
,因此 409 似乎是来自控制器的适当答案,因为正在执行 orElseGet
部分。
如果我没记错的话,你可以把测试 class 注释精简一点,只使用 @WebMvcTest
。这种测试应该够用了,速度应该会快一点。