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

问题描述 投票:0回答:2

控制器

@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 设置?

testng spring-test mockmvc spring-test-mvc
2个回答
11
投票

是否可以将

MethodValidationPostProcessor
bean 添加到独立设置中?

不,不幸的是,使用

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

一旦解决了 SPR-6380(目前在 Spring Framework 5.x 待办事项中),您将不再需要依赖

MethodValidationPostProcessor
。但是,在此期间,您需要切换到使用
MockMvcBuilders.webAppContextSetup()
,以便能够测试通过
MethodValidationPostProcessor
添加到控制器的行为。

原来的错误建议

我认为直接这样做是不可能的;但是,您可以创建

StandaloneMockMvcBuilder
的自定义子类,覆盖
initWebAppContext()
方法,委托给
super.initWebAppContext()
创建
WebApplicationContext
,然后通过
MethodValidationPostProcessor
以编程方式注册
org.springframework.test.web.servlet.setup.StubWebApplicationContext.addBean(String, Object)
bean。


0
投票

对我来说,使用

spring-test:6.1.14
,使用
MockMvc.setValidator
就足够了,这足以在请求无效时抛出 MethodArgumentNotValidException。

import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
...


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

我正在使用部署在 Tomcat 10.1.x 上的 Spring 应用程序,因此我还必须添加依赖项才能使其正常工作:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-el-api</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper-el</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
© www.soinside.com 2019 - 2024. All rights reserved.