如何使用JUnit5测试@Validated类中带@NotBlank注解的方法参数校验逻辑
如何使用JUnit5测试@Validated类中带@NotBlank注解的方法参数校验逻辑
我之前刚好处理过类似的场景——当校验规则直接标注在方法参数上而不是实体类里时,常规的实体校验测试思路确实不太适用。不过结合JUnit 5和Spring的测试支持,我们可以轻松验证这个方法级的校验逻辑,下面一步步来拆解:
核心思路说明
因为@Validated是Spring提供的注解,它依靠AOP切面来实现方法级的参数校验,必须让Spring容器管理目标类的实例,才能触发校验逻辑。如果直接new Foo()调用方法,Spring的校验切面根本不会介入,自然不会触发校验。所以我们的测试需要启动Spring上下文,让Spring来创建并管理Foo的实例。
测试步骤与代码示例
1. 确保依赖到位
如果是Spring Boot项目,只需要引入spring-boot-starter-test依赖即可,它已经包含了JUnit 5、Spring Test以及Jakarta Validation的相关依赖:
<!-- Maven依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2. 编写测试类
我们可以用@ExtendWith(SpringExtension.class)来启用Spring的JUnit 5支持,再通过@ContextConfiguration指定要加载的类(这里就是我们的Foo类),这样就能启动一个轻量的Spring上下文:
import jakarta.validation.ConstraintViolationException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {Foo.class}) class FooValidationTest { // 让Spring注入管理的Foo实例,而不是自己new @Autowired private Foo foo; @Test void bar_WithBlankBaz_ShouldThrowValidationException() { // 测试空字符串、null、空白字符三种场景,都会触发@NotBlank校验 assertThrows(ConstraintViolationException.class, () -> foo.bar("")); assertThrows(ConstraintViolationException.class, () -> foo.bar(null)); assertThrows(ConstraintViolationException.class, () -> foo.bar(" ")); } @Test void bar_WithValidBaz_ShouldNotThrowException() { // 合法参数不会触发异常,执行方法无报错即通过测试 foo.bar("Hello, Validation!"); } // 可选:验证具体的错误提示信息 @Test void bar_WithBlankBaz_ShouldReturnCorrectErrorMessage() { ConstraintViolationException exception = assertThrows(ConstraintViolationException.class, () -> foo.bar("")); // 获取第一个校验违规的信息(这里只有一个参数违规) String errorMsg = exception.getConstraintViolations().iterator().next().getMessage(); // 默认@NotBlank的提示是"must not be blank",如果自定义了message就写对应的内容 assertEquals("must not be blank", errorMsg); } }
3. Spring Boot项目的简化写法
如果你的项目是Spring Boot,直接用@SpringBootTest注解就可以,它会自动扫描当前包下的组件,不需要手动指定@ContextConfiguration,测试类会更简洁:
import jakarta.validation.ConstraintViolationException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import static org.junit.jupiter.api.Assertions.assertThrows; @SpringBootTest class FooValidationTest { @Autowired private Foo foo; @Test void bar_WithInvalidBaz_ThrowsException() { assertThrows(ConstraintViolationException.class, () -> foo.bar("")); } }
关键注意点
- 绝对不能直接
new Foo()来测试,因为这样的实例不在Spring容器中,不会触发@Validated的AOP校验切面。 @NotBlank注解的校验规则是:字符串不能为null,且去除首尾空格后长度大于0,所以测试要覆盖这几种违规场景。
内容来源于stack exchange
相关产品推荐
相关产品推荐

