Spring boot @MockMvcTest MockHttpServletResponse 始终返回空主体

I h*_*ers 1 java spring unit-testing mockito spring-boot

我正在努力进行一个简单的弹簧启动休息控制器测试,该测试总是返回空的身体响应。

\n

这是我的测试代码:

\n
@WebMvcTest(AdminRestController.class)\n@AutoConfigureMockMvc(addFilters = false)\npublic class PatientsUnitTest {\n\n    @Autowired\n    private MockMvc mvc;\n\n    @Autowired\n    private ObjectMapper objectMapper;\n\n    @MockBean\n    private PatientsService patientsService;\n\n    @MockBean\n    private TherapistsService therapistsService;\n\n    @MockBean\n    private TherapySchedulesService therapySchedulesService;\n\n    @Test\n    public void canAddPatient() throws Exception {\n        PatientsSaveRequestDto patientsSaveRequestDto = new PatientsSaveRequestDto();\n        patientsSaveRequestDto.setName("Sofia");\n        patientsSaveRequestDto.setPhone("01012345678");\n        Patients patient = patientsSaveRequestDto.toEntity();\n\n        when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);\n\n        final ResultActions actions = mvc.perform(post("/admin/patient")\n                .contentType(MediaType.APPLICATION_JSON_VALUE)\n                .characterEncoding(StandardCharsets.UTF_8.name())\n                .content(objectMapper.writeValueAsString(patientsSaveRequestDto)))\n                .andDo(print());\n\n        actions\n                .andExpect(status().isOk())\n                .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))\n                .andExpect(jsonPath("name", is(patient.getName())))\n                .andDo(print());\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

我的控制器:

\n
@RestController\n@RequiredArgsConstructor\npublic class AdminRestController {\n    private final PatientsService patientsService;\n    private final TherapistsService therapistsService;\n    private final TherapySchedulesService therapySchedulesService;\n\n    @PostMapping("/admin/patient")\n    @ResponseStatus(HttpStatus.OK)\n    @Operation(summary = "Create a patient")\n    public Patients cratePatient(\n            @RequestBody @Valid PatientsSaveRequestDto patientsSaveRequestDto\n    ) {\n        return patientsService.createPatient(patientsSaveRequestDto);\n    }\n\n// PatientsService\n@Transactional\n    public Patients createPatient(PatientsSaveRequestDto patientsSaveRequestDto){\n        return patientsRepository.save(patientsSaveRequestDto.toEntity());\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

这是 print() 的结果:

\n
MockHttpServletRequest:\n      HTTP Method = POST\n      Request URI = /admin/patient\n       Parameters = {}\n          Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"53"]\n             Body = {"name":"sofia","phone":"01012345678","tel":null}\n    Session Attrs = {}\n\nHandler:\n             Type = com.ussoft.dosu.web.controller.admin.AdminRestController\n           Method = com.ussoft.dosu.web.controller.admin.AdminRestController#cratePatient(PatientsSaveRequestDto)\n\nAsync:\n    Async started = false\n     Async result = null\n\nResolved Exception:\n             Type = null\n\nModelAndView:\n        View name = null\n             View = null\n            Model = null\n\nFlashMap:\n       Attributes = null\n\nMockHttpServletResponse:\n           Status = 200\n    Error message = null\n          Headers = []\n     Content type = null\n             Body = \n    Forwarded URL = null\n   Redirected URL = null\n          Cookies = []\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所看到的,请求已正确发送,但响应值均为空。

\n

当我使用 @SpringBootTest 和 Rest Assured 测试相同的控制器时,它工作正常。

\n

我正在使用 Spring boot 2.3.1、Junit5

\n
\n

编辑-添加PatientsSaveRequestDto

\n
MockHttpServletRequest:\n      HTTP Method = POST\n      Request URI = /admin/patient\n       Parameters = {}\n          Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"53"]\n             Body = {"name":"sofia","phone":"01012345678","tel":null}\n    Session Attrs = {}\n\nHandler:\n             Type = com.ussoft.dosu.web.controller.admin.AdminRestController\n           Method = com.ussoft.dosu.web.controller.admin.AdminRestController#cratePatient(PatientsSaveRequestDto)\n\nAsync:\n    Async started = false\n     Async result = null\n\nResolved Exception:\n             Type = null\n\nModelAndView:\n        View name = null\n             View = null\n            Model = null\n\nFlashMap:\n       Attributes = null\n\nMockHttpServletResponse:\n           Status = 200\n    Error message = null\n          Headers = []\n     Content type = null\n             Body = \n    Forwarded URL = null\n   Redirected URL = null\n          Cookies = []\n
Run Code Online (Sandbox Code Playgroud)\n

Les*_*iak 6

您需要为 提供 equals 方法PatientsSaveRequestDto

当您在模拟上执行方法时,Mockito 需要检查是否为调用该方法的参数指定了任何行为。

  • 如果参数匹配,则返回记录的结果,
  • 如果参数不匹配,则返回方法返回类型的默认值(所有对象为 null,数字为零,布尔为 false)

您通过以下调用记录了该行为:

when(patientsService.createPatient(patientsSaveRequestDto)).thenReturn(patient);
Run Code Online (Sandbox Code Playgroud)

这意味着 的实际参数将与createPatient进行比较。patientsSaveRequestDtoequals

请注意,可以通过使用ArgumentMatchers来更改此行为。

您的测试中的patientsSaveRequestDto和实际参数createPatient不相等,因为:

  • 你没有定义 equals 方法
  • 他们是不同的实例
  • 因此,继承的 Object.equals 返回 false

您有 2 个不同的实例,因为您创建了 @WebMvcTest。您发送到控制器的数据patientsSaveRequestDto首先序列化为 String,然后反序列化,这就是创建第二个实例的方式。