Spring 始终启动@MockMvcTest MockHttpServletResponse returns 空体
Spring boot @MockMvcTest MockHttpServletResponse always returns empty body
我正在努力进行简单的 spring 启动休息控制器测试,它总是 return 空体响应。
这是我的测试代码:
@WebMvcTest(AdminRestController.class)
@AutoConfigureMockMvc(addFilters = false)
public class PatientsUnitTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private PatientsService patientsService;
@MockBean
private TherapistsService therapistsService;
@MockBean
private TherapySchedulesService therapySchedulesService;
@Test
public void canAddPatient() throws Exception {
PatientsSaveRequestDto patientsSaveRequestDto = new PatientsSaveRequestDto();
patientsSaveRequestDto.setName("Sofia");
patientsSaveRequestDto.setPhone("01012345678");
Patients patient = patientsSaveRequestDto.toEntity();
when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);
final ResultActions actions = mvc.perform(post("/admin/patient")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.characterEncoding(StandardCharsets.UTF_8.name())
.content(objectMapper.writeValueAsString(patientsSaveRequestDto)))
.andDo(print());
actions
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("name", is(patient.getName())))
.andDo(print());
}
我的控制器:
@RestController
@RequiredArgsConstructor
public class AdminRestController {
private final PatientsService patientsService;
private final TherapistsService therapistsService;
private final TherapySchedulesService therapySchedulesService;
@PostMapping("/admin/patient")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "Create a patient")
public Patients cratePatient(
@RequestBody @Valid PatientsSaveRequestDto patientsSaveRequestDto
) {
return patientsService.createPatient(patientsSaveRequestDto);
}
// PatientsService
@Transactional
public Patients createPatient(PatientsSaveRequestDto patientsSaveRequestDto){
return patientsRepository.save(patientsSaveRequestDto.toEntity());
}
这是 print() 的结果:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /admin/patient
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"53"]
Body = {"name":"sofia","phone":"01012345678","tel":null}
Session Attrs = {}
Handler:
Type = com.ussoft.dosu.web.controller.admin.AdminRestController
Method = com.ussoft.dosu.web.controller.admin.AdminRestController#cratePatient(PatientsSaveRequestDto)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
如您所见,请求已正确发送,但响应值为空。
当我使用@SpringBootTest 和 Rest Assured 测试同一个控制器时,它工作正常。
我正在使用 Spring boot 2.3.1,Junit5
编辑 - 添加 PatientsSaveRequestDto
@Getter
@Setter
@NoArgsConstructor
public class PatientsSaveRequestDto {
@NotBlank(message = "이름은 필수 입력사항입니다.")
private String name;
private String phone;
private String tel;
public Patients toEntity(){
return Patients.builder()
.name(name)
.phone(phone)
.tel(tel)
.build();
}
}
您需要为 PatientsSaveRequestDto
提供 equals 方法。
当您在 mock 上执行方法时,Mockito 需要检查是否为调用该方法的参数指定了任何行为。
- 如果参数匹配,记录结果为returned,
- 如果参数不匹配,方法 return 类型的默认值是 returned(所有对象为 null,数字为零,bool 为 false)
您通过以下调用记录了该行为:
when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);
这意味着 createPatient
的实际参数将与 patientsSaveRequestDto
和 equals
进行比较。
请注意,可以通过使用 ArgumentMatchers 来更改此行为。
测试中的 patientsSaveRequestDto
和 createPatient
的实际参数不相等,因为:
- 你没有定义 equals 方法
- 它们是不同的实例
- 因此,继承的Object.equals returns false
您有 2 个不同的实例,因为您创建了 @WebMvcTest。
您发送到控制器的 patientsSaveRequestDto
首先序列化为 String,然后反序列化,这就是创建第二个实例的方式。
我正在努力进行简单的 spring 启动休息控制器测试,它总是 return 空体响应。
这是我的测试代码:
@WebMvcTest(AdminRestController.class)
@AutoConfigureMockMvc(addFilters = false)
public class PatientsUnitTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private PatientsService patientsService;
@MockBean
private TherapistsService therapistsService;
@MockBean
private TherapySchedulesService therapySchedulesService;
@Test
public void canAddPatient() throws Exception {
PatientsSaveRequestDto patientsSaveRequestDto = new PatientsSaveRequestDto();
patientsSaveRequestDto.setName("Sofia");
patientsSaveRequestDto.setPhone("01012345678");
Patients patient = patientsSaveRequestDto.toEntity();
when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);
final ResultActions actions = mvc.perform(post("/admin/patient")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.characterEncoding(StandardCharsets.UTF_8.name())
.content(objectMapper.writeValueAsString(patientsSaveRequestDto)))
.andDo(print());
actions
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("name", is(patient.getName())))
.andDo(print());
}
我的控制器:
@RestController
@RequiredArgsConstructor
public class AdminRestController {
private final PatientsService patientsService;
private final TherapistsService therapistsService;
private final TherapySchedulesService therapySchedulesService;
@PostMapping("/admin/patient")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "Create a patient")
public Patients cratePatient(
@RequestBody @Valid PatientsSaveRequestDto patientsSaveRequestDto
) {
return patientsService.createPatient(patientsSaveRequestDto);
}
// PatientsService
@Transactional
public Patients createPatient(PatientsSaveRequestDto patientsSaveRequestDto){
return patientsRepository.save(patientsSaveRequestDto.toEntity());
}
这是 print() 的结果:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /admin/patient
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"53"]
Body = {"name":"sofia","phone":"01012345678","tel":null}
Session Attrs = {}
Handler:
Type = com.ussoft.dosu.web.controller.admin.AdminRestController
Method = com.ussoft.dosu.web.controller.admin.AdminRestController#cratePatient(PatientsSaveRequestDto)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
如您所见,请求已正确发送,但响应值为空。
当我使用@SpringBootTest 和 Rest Assured 测试同一个控制器时,它工作正常。
我正在使用 Spring boot 2.3.1,Junit5
编辑 - 添加 PatientsSaveRequestDto
@Getter
@Setter
@NoArgsConstructor
public class PatientsSaveRequestDto {
@NotBlank(message = "이름은 필수 입력사항입니다.")
private String name;
private String phone;
private String tel;
public Patients toEntity(){
return Patients.builder()
.name(name)
.phone(phone)
.tel(tel)
.build();
}
}
您需要为 PatientsSaveRequestDto
提供 equals 方法。
当您在 mock 上执行方法时,Mockito 需要检查是否为调用该方法的参数指定了任何行为。
- 如果参数匹配,记录结果为returned,
- 如果参数不匹配,方法 return 类型的默认值是 returned(所有对象为 null,数字为零,bool 为 false)
您通过以下调用记录了该行为:
when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);
这意味着 createPatient
的实际参数将与 patientsSaveRequestDto
和 equals
进行比较。
请注意,可以通过使用 ArgumentMatchers 来更改此行为。
测试中的 patientsSaveRequestDto
和 createPatient
的实际参数不相等,因为:
- 你没有定义 equals 方法
- 它们是不同的实例
- 因此,继承的Object.equals returns false
您有 2 个不同的实例,因为您创建了 @WebMvcTest。
您发送到控制器的 patientsSaveRequestDto
首先序列化为 String,然后反序列化,这就是创建第二个实例的方式。