如何在 Spring 启动测试中模拟 BindingResult
How to mock BindingResult in Spring Boot Test
我有以下控制器:
@RestController
@RequestMapping(value = ROOT_MAPPING)
public class GatewayController {
@Autowired
private RequestValidator requestValidator;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(requestValidator);
}
@PostMapping(value = REDIRECT_MAPPING)
public ResponseEntity<ResponseDTO> redirectEndpoint(@Validated @RequestBody RequestDTO requestDTO, BindingResult result) {
if (result.hasErrors()) {
// Handle validation errors
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
// Do other stuff
return ResponseEntity.status(HttpStatus.OK).build();
}
}
而这个测试class:
@RunWith(SpringRunner.class)
@WebMvcTest(GatewayController.class)
public class GatewayControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RequestValidator requestValidator;
@MockBean
private BindingResult bindingResult;
private JacksonTester<RequestDTO> requestJacksonTester;
@Before
public void setUp() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
Mockito.when(requestValidator.supports(ArgumentMatchers.any())).thenReturn(true);
}
@Test
public void whenRedirectWithValidationErrorsThenBadRequestReturned() throws Exception {
RequestDTO request = new RequestDTO();
// Set some values
Mockito.when(bindingResult.hasErrors()).thenReturn(true);
mockMvc.perform(MockMvcRequestBuilders.post(ROOT_MAPPING + REDIRECT_MAPPING)
.contentType(MediaType.APPLICATION_JSON)
.content(requestJacksonTester.write(request).getJson()))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
当我运行这个代码测试用例失败的原因是:状态
预期:400
实际:200
所以,我想做的是模拟 BindingResult
作为参数传递给 Controller 中的 redirectEndpoint
方法,以便在调用 bindingResult.hasErrors()
时应该 return true 测试用例通过。
我做了很多搜索,但都没有成功。有什么建议吗?
提前致谢。
BindingResult
不是 ApplicationContext
中的 bean。因此,你不能通过 @MockBean
.
mock
Spring MVC 为每个传入的 HTTP 请求创建了一个 BindingResult
。
因此,您不想模拟 BindingResult
。事实上,您可能也不想模拟 RequestValidator
的行为。相反,您应该理想地使用 RequestValidator
的真实实现,传入 无效 请求数据(通过 MockMvc
),然后相应地验证响应。
请注意,在测试 class 中,您应该能够通过 @Import(RequestValidator.class)
包含 您的 RequestValidator
的实际实现。 20=]
我有以下控制器:
@RestController
@RequestMapping(value = ROOT_MAPPING)
public class GatewayController {
@Autowired
private RequestValidator requestValidator;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(requestValidator);
}
@PostMapping(value = REDIRECT_MAPPING)
public ResponseEntity<ResponseDTO> redirectEndpoint(@Validated @RequestBody RequestDTO requestDTO, BindingResult result) {
if (result.hasErrors()) {
// Handle validation errors
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
// Do other stuff
return ResponseEntity.status(HttpStatus.OK).build();
}
}
而这个测试class:
@RunWith(SpringRunner.class)
@WebMvcTest(GatewayController.class)
public class GatewayControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RequestValidator requestValidator;
@MockBean
private BindingResult bindingResult;
private JacksonTester<RequestDTO> requestJacksonTester;
@Before
public void setUp() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
Mockito.when(requestValidator.supports(ArgumentMatchers.any())).thenReturn(true);
}
@Test
public void whenRedirectWithValidationErrorsThenBadRequestReturned() throws Exception {
RequestDTO request = new RequestDTO();
// Set some values
Mockito.when(bindingResult.hasErrors()).thenReturn(true);
mockMvc.perform(MockMvcRequestBuilders.post(ROOT_MAPPING + REDIRECT_MAPPING)
.contentType(MediaType.APPLICATION_JSON)
.content(requestJacksonTester.write(request).getJson()))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
当我运行这个代码测试用例失败的原因是:状态 预期:400 实际:200
所以,我想做的是模拟 BindingResult
作为参数传递给 Controller 中的 redirectEndpoint
方法,以便在调用 bindingResult.hasErrors()
时应该 return true 测试用例通过。
我做了很多搜索,但都没有成功。有什么建议吗?
提前致谢。
BindingResult
不是 ApplicationContext
中的 bean。因此,你不能通过 @MockBean
.
Spring MVC 为每个传入的 HTTP 请求创建了一个 BindingResult
。
因此,您不想模拟 BindingResult
。事实上,您可能也不想模拟 RequestValidator
的行为。相反,您应该理想地使用 RequestValidator
的真实实现,传入 无效 请求数据(通过 MockMvc
),然后相应地验证响应。
请注意,在测试 class 中,您应该能够通过 @Import(RequestValidator.class)
包含 您的 RequestValidator
的实际实现。 20=]