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

Bax*_*Bax 5 testng spring-test spring-test-mvc 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Sam*_*nen 8

是否可以将MethodValidationPostProcessorbean 添加到独立设置中?

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

一旦SPR-6380得到解决(当前在 Spring Framework 5.x 待办事项中),您将不再需要依赖MethodValidationPostProcessor. 但是,在此期间,您将需要切换到使用MockMvcBuilders.webAppContextSetup(),以便能够测试通过 添加到控制器的行为MethodValidationPostProcessor

原来的错误建议

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