Spring MockMvc忽略未知字段无法触发@Valid校验如何解决
问题本质
你遇到的现象由两个核心原因导致:
- 未知字段拦截不是
@Valid注解提供的能力,是Jackson反序列化组件的DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES特性开启后,遇到请求体中不存在于接收类的字段时直接抛出异常的效果 - 你使用
standaloneSetup方式构建的MockMvc属于轻量化测试环境,不会自动加载项目中全局配置的Jackson参数,也不会自动注册JSR-380校验器,因此会出现和实际运行环境不一致的表现
解决步骤
1. 手动配置Jackson消息转换器
自定义MappingJackson2HttpMessageConverter,开启未知字段报错的特性,注册到MockMvc环境中。
2. 手动注册校验器
确保@Valid注解的参数校验逻辑正常生效。
修改后的测试代码示例:
import com.fasterxml.jackson.databind.DeserializationFeature; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; // 构造请求 MockHttpServletRequestBuilder builder = MockMvcRequestBuilders .post("/path" ) .content("{\"fakeField\":\"fake\",\"userId\":\"clientId\"}") .contentType(MediaType.APPLICATION_JSON_VALUE); String responseMessage = "Error message"; // 自定义Jackson转换器,开启未知字段拦截 MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); jacksonConverter.getObjectMapper().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // 初始化校验器 LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); validator.afterPropertiesSet(); // 构建MockMvc时注入自定义配置 this.mockMvc = standaloneSetup(myController) .setMessageConverters(jacksonConverter) .setValidator(validator) .build(); // 执行测试 this.mockMvc .perform(builder) .andDo(print()) .andExpect(status().is(HttpStatus.BAD_REQUEST.value())) .andExpect(content().string(containsString(responseMessage)));
注意事项
如果你的RequestClass类上标注了@JsonIgnoreProperties(ignoreUnknown = true),会覆盖全局Jackson配置,此时即使开启了FAIL_ON_UNKNOWN_PROPERTIES也不会拦截未知字段,需要移除该注解或者将ignoreUnknown属性设为false。
内容的提问来源于stack exchange,提问作者Tilmiz
相关产品推荐
相关产品推荐

