如何在 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=]