控制器
@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 设置?
是否可以将
bean 添加到独立设置中?MethodValidationPostProcessor
不,不幸的是,使用
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。对我来说,使用
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>