如何为独立 MockMvc 启用控制器参数验证

How to enable controller parameter validation for standalone MockMvc

控制器

@RestController
@Validated
class MyController {

    @GetMapping("/foo")
    public String unwrapped(@Min(1) @RequestParam("param") int param) {
        return Integer.toString(param);
    }

    @GetMapping("/bar")
    public String wrapped(@ModelAttribute @Valid Wrapper bean) {
        return Integer.toString(bean.param);
    }

    static class Wrapper {

        @Min(1)
        int param;

        public void setParam(final int param) {
            this.param = param;
        }
    }
}

测试

public class MyControllerTest {

    MyController controller = new MyController();
    MockMvc mockMvc = MockMvcBuilders
            .standaloneSetup(this.controller)
            .build();

    @Test // fails
    public void unwrapped() throws Exception {
        this.mockMvc.perform(get("/foo")
                .param("param", "0"))
                .andExpect(status().isBadRequest());
    }

    @Test // passes
    public void wrapped() throws Exception {
        this.mockMvc.perform(get("/bar")
                .param("param", "0"))
                .andExpect(status().isBadRequest());
    }
}

要在 spring 中启用(展开的)方法参数验证,必须使用 @Validated 注释控制器并且必须将 MethodValidationPostProcessor 添加到上下文中。
是否可以将 MethodValidationPostProcessor bean 添加到独立设置中?
问题可能会简化为如何将 BeanPostProcessor 添加到独立的 MockMvc 设置中?

Is it possible to add the MethodValidationPostProcessor bean to the standalone setup ?

不,不幸的是,在使用 MockMvcBuilders.standaloneSetup() 时这是不可能的,因为这会在幕后创建一个 StubWebApplicationContext 支持 BeanPostProcessor s.

一旦 SPR-6380 得到解决(目前在 Spring 框架 5.x 积压中),您将不再需要依赖 MethodValidationPostProcessor。但是,在此期间,您需要切换到 MockMvcBuilders.webAppContextSetup() 的使用,以便能够测试通过 MethodValidationPostProcessor.

添加到您的控制器的行为

原错误建议

我认为直接这样做是不可能的;但是,您可以创建 StandaloneMockMvcBuilder 的自定义子类来覆盖 initWebAppContext() 方法,委托给 super.initWebAppContext() 来创建 WebApplicationContext,然后注册 MethodValidationPostProcessor bean以编程方式通过 org.springframework.test.web.servlet.setup.StubWebApplicationContext.addBean(String, Object).