spring boot参数校验单元测试应使用@webmvctest配合mockmvc,验证@valid注解触发及错误信息返回;需添加spring-boot-starter-validation和spring-boot-starter-test依赖,通过json-path断言响应体错误字段,避免使用@springboottest或直接调用controller方法。

Spring Boot 中参数校验的单元测试,核心是模拟 Controller 层接收请求时的校验行为,验证 @Valid 或 @Validated 注解是否按预期触发、错误信息是否正确返回。关键在于不启动完整 Web 容器(避免用 @SpringBootTest),而是用 @WebMvcTest 配合 MockMvc 进行轻量级测试。
准备校验相关的测试依赖
确保项目中已引入以下依赖(Maven):
-
spring-boot-starter-validation(Spring Boot 2.3+ 默认不包含,需显式添加) -
spring-boot-starter-test(含mockmvc、junit-jupiter等)
定义带校验的 DTO 和 Controller
例如:
public class UserDTO {
@NotBlank(message = "用户名不能为空")
private String username;
@Min(value = 18, message = "年龄不能小于18")
private Integer age;
// getter/setter...
}
Controller 方法使用 @Valid:
@PostMapping("/users")
public ResponseEntity<string> createUser(@Valid @RequestBody UserDTO dto) {
return ResponseEntity.ok("success");
}</string>
编写 @WebMvcTest 单元测试
用 @WebMvcTest 只加载 Web 层组件,自动配置 MockMvc 和校验器(LocalValidatorFactoryBean):
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void shouldReturn400WhenUsernameIsEmpty() throws Exception {
String invalidJson = "{\"username\":\"\",\"age\":25}";
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(invalidJson))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.message").value("用户名不能为空"));
}
@Test
void shouldReturn400WhenAgeTooSmall() throws Exception {
String invalidJson = "{\"username\":\"jack\",\"age\":17}";
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(invalidJson))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.message").value("年龄不能小于18"));
}
}
说明:
- 测试类上加
@WebMvcTest(UserController.class),只加载该 Controller 及其依赖(如@Valid所需的校验器) - 不用手动配置
Validator,Spring Boot 自动注册了标准 JSR-303 校验器 - 若 Controller 返回的是全局异常处理(如
@ControllerAdvice捕获MethodArgumentNotValidException),测试时会自动生效,无需额外配置 - 建议配合
json-path(spring-boot-starter-test已包含)断言响应体中的错误字段
补充:测试分组校验(@Validated)
若使用校验分组(如 @Validated(UserCreate.class)),需确保测试用的 DTO 实例满足分组约束逻辑,并在测试中传入对应数据。Spring 的校验器会自动识别分组,无需额外设置。
注意:不要用 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 做这类测试——太重,且掩盖了校验链路细节;也不要跳过校验直接调 Controller 方法(如 controller.createUser(dto)),那样绕过了 Spring 的参数解析和校验机制,测试无效。











