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

Testng 如何为独立的MockMvc启用控制器参数验证,testng,spring-test,mockmvc,spring-test-mvc,Testng,Spring Test,Mockmvc,Spring Test Mvc,控制器 @RestController @Validated class MyController { @GetMapping("/foo") public String unwrapped(@Min(1) @RequestParam("param") int param) { return Integer.toString(param); } @GetMapping("/bar")

控制器

@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;
        }
    }
}
试验

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

是否可以将
MethodValidationPostProcessor
bean添加到独立设置中

不,遗憾的是,在使用
MockMvcBuilders.standaloneSetup()
时,这是不可能的,因为这会在后台创建一个
StubWebApplicationContext
,而支持
beanpstoprocessor
s

一旦解决了(目前在SpringFramework5.x积压工作中),您将不再需要依赖
MethodValidationPostProcessor
。但是,在此期间,您需要切换到使用
MockMvcBuilders.webAppContextSetup()
,以便能够测试通过
MethodValidationPostProcessor
添加到控制器的行为

原始错误建议
我认为不可能直接做到这一点;但是,您可以创建
StandaloneMockMvcBuilder
的自定义子类,该子类重写
initWebAppContext()
方法,委托给
super.initWebAppContext()
以创建
WebApplicationContext
,然后通过
org.springframework.test.web.servlet.setup.StubWebApplicationContext.addBean(字符串,对象)
以编程方式注册
MethodValidationPostProcessor
bean。出于好奇,您是否在部署应用程序时验证了您的
unwrapped()
方法是否正确有效?我这样问是因为
@RequestParam
不支持验证。有关详细信息,请参阅以下JIRA问题:没关系:我刚刚注意到该问题中的这条评论:确实如此,出现了
ConstraintViolationException
。我很抱歉:我最初的建议根本不起作用,因为
StubWebApplicationContext
明确不支持
BeanPostProcessor
s。但是,我将编辑我的答案以包含权威响应。它正在为\@validatedcontroller工作,其方法包括dto参数及其属性上的验证注释。但不适用于直接针对控制器方法参数的验证注释。对于后一种情况,您需要集成测试(\@RunWith(SpringRunner.class和\@SpringMvcTest)。不要忘记,类上的\@validated会在ConstraintValidationException上产生500 http错误,对于所需的错误请求响应,您必须为每个异常类实现异常处理程序。
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());
    }
}