skills;
-
+
// getter/setter...
}
```
@@ -468,17 +477,19 @@ public class CompleteValidationDto {
public class UserDto {
// 分组接口定义
public interface BasicGroup {}
+
public interface AdvancedGroup {}
+
public interface StudentGroup {}
+
public interface TeacherGroup {}
-
+
@NotBlank(message = "名称不能为空")
private String name;
-
- @Max(value = 200, message = "高级组年龄必须小于等于200", groups = AdvancedGroup.class)
+ @Max(value = 200, message = "高级组年龄必须小于等于 200", groups = AdvancedGroup.class)
private Integer age;
-
+
// getter/setter...
}
```
@@ -488,7 +499,7 @@ public class UserDto {
@Validated(UserDto.AdvancedGroup.class)
public class AdvancedUserService {
public void processAdvancedUser(@Valid UserDto user) {
- // 只会应用AdvancedGroup分组的校验规则
+ // 只会应用 AdvancedGroup 分组的校验规则
}
}
```
@@ -497,36 +508,35 @@ public class AdvancedUserService {
### 核心组件
-1. **ValidationHandler**:校验入口类,通过AOP方式拦截带有`@Validated`注解的类或方法,自动触发校验逻辑。
-
-2. **Hibernate Validator**:底层使用Hibernate Validator作为校验引擎。
-
+1. **ValidationHandler**:校验入口类,通过 AOP 方式拦截带有 `@Validated` 注解的类或方法,自动触发校验逻辑。
+2. **Hibernate Validator**:底层使用 Hibernate Validator 作为校验引擎。
3. **ConstraintViolationException**:校验失败时抛出的异常,包含详细的错误信息。
### 校验流程
-1. 当调用带有`@Validated`注解的类的方法时,`ValidationHandler`会拦截该调用
+1. 当调用带有 `@Validated` 注解的类的方法时,`ValidationHandler` 会拦截该调用
2. 检查方法参数是否包含校验注解
-3. 使用Hibernate Validator对参数进行校验
-4. 如果校验失败,抛出`ConstraintViolationException`异常
+3. 使用 Hibernate Validator 对参数进行校验
+4. 如果校验失败,抛出 `ConstraintViolationException` 异常
5. 可通过全局异常处理器捕获并处理校验异常
-
## 12.3.4 版本差异
两个插件的主要差异:
| 特性 | fit-hibernate-validation | fit-hibernate-validation-jakarta |
-|------|-------------------------|----------------------------------|
+|-------------|--------------------------|----------------------------------|
| 校验规范 | javax.validation | jakarta.validation |
-| Hibernate版本 | 6.2.5.Final | 9.0.1.Final |
-| 适用环境 | 传统Java EE | Jakarta EE |
+| Hibernate 版本 | 6.2.5.Final | 9.0.1.Final |
+| 适用环境 | 传统 Java EE | Jakarta EE |
| 包名空间 | javax.validation.* | jakarta.validation.* |
选择建议:
-- 新项目推荐使用Jakarta版本
+
+- 新项目推荐使用 Jakarta 版本
- 现有项目根据依赖情况选择对应版本
- 两个版本功能完全一致,仅包名空间不同
## 12.3.5 校验的国际化
+
与校验扩展一样,需要手动处理报错信息中的内容,以完成国际化功能
\ No newline at end of file
diff --git a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/main/java/modelengine/fitframework/validation/ValidationHandler.java b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/main/java/modelengine/fitframework/validation/ValidationHandler.java
index c5c4186e8..37d38a5af 100644
--- a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/main/java/modelengine/fitframework/validation/ValidationHandler.java
+++ b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/main/java/modelengine/fitframework/validation/ValidationHandler.java
@@ -6,6 +6,12 @@
package modelengine.fitframework.validation;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import jakarta.validation.ValidatorFactory;
+import jakarta.validation.executable.ExecutableValidator;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Scope;
import modelengine.fitframework.aop.JoinPoint;
@@ -23,13 +29,6 @@
import java.util.Arrays;
import java.util.Set;
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
-import jakarta.validation.Validation;
-import jakarta.validation.Validator;
-import jakarta.validation.ValidatorFactory;
-import jakarta.validation.executable.ExecutableValidator;
-
/**
* 校验入口类。
*
@@ -55,14 +54,14 @@ public ValidationHandler() {
}
/**
- * 方法参数校验处理
+ * 方法参数校验处理。
*
- * @param joinPoint 被拦截的连接点 {@link JoinPoint}
- * @param validated 连接点上携带的校验注解 {@link Validated}
+ * @param joinPoint 被拦截的连接点 {@link JoinPoint}。
+ * @param validated 连接点上携带的校验注解 {@link Validated}。
*/
@Before(value = "@target(validated) && execution(public * *(..))", argNames = "joinPoint, validated")
private void handle(JoinPoint joinPoint, Validated validated) {
- // 检查方法参数是否包含被 javax.validation.Constraint 标注的校验注解
+ // 检查方法参数是否包含被 jakarta.validation.Constraint 标注的校验注解。
if (hasJakartaConstraintAnnotations(joinPoint.getMethod().getParameters())) {
ExecutableValidator execVal = this.validator.forExecutables();
Set> result = execVal.validateParameters(joinPoint.getTarget(),
@@ -82,65 +81,65 @@ public void close() {
}
/**
- * 检查方法参数是否包含 jakarta.validation 校验注解
+ * 检查方法参数是否包含 jakarta.validation 校验注解。
*
- * @param parameters 方法参数数组 {@link Parameter[]}
- * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false
+ * @param parameters 方法参数数组 {@link Parameter[]}。
+ * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false {@code boolean}。
*/
private boolean hasJakartaConstraintAnnotations(Parameter[] parameters) {
- return Arrays.stream(parameters)
- .anyMatch(this::hasConstraintAnnotationsInParameter);
+ return Arrays.stream(parameters).anyMatch(this::hasConstraintAnnotationsInParameter);
}
/**
- * 检查参数及其泛型类型参数是否包含校验注解
- * @param parameter 方法参数 {@link Parameter}
- * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false
+ * 检查参数及其泛型类型参数是否包含校验注解。
+ *
+ * @param parameter 方法参数 {@link Parameter}。
+ * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false {@code boolean}。
*/
private boolean hasConstraintAnnotationsInParameter(Parameter parameter) {
return hasConstraintAnnotationsInType(parameter.getAnnotatedType());
}
/**
- * 判断参数注解类型,解析参数本身注解及其泛型类型参数注解
- * @param annotatedType 参数注解类型 {@link AnnotatedType}
- * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false
+ * 判断参数注解类型,解析参数本身注解及其泛型类型参数注解。
+ *
+ * @param annotatedType 参数注解类型 {@link AnnotatedType}。
+ * @return 如果包含 jakarta.validation 标注的校验注解则返回 true,否则返回 false {@code boolean}。
*/
private boolean hasConstraintAnnotationsInType(AnnotatedType annotatedType) {
- // 检查当前类型上的注解
+ // 检查当前类型上的注解。
if (Arrays.stream(annotatedType.getAnnotations()).anyMatch(this::isJakartaConstraintAnnotation)) {
return true;
}
-
- // 如果是参数化类型,递归检查类型参数
+
+ // 如果是参数化类型,递归检查类型参数。
if (annotatedType instanceof AnnotatedParameterizedType) {
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) annotatedType;
return Arrays.stream(parameterizedType.getAnnotatedActualTypeArguments())
.anyMatch(this::hasConstraintAnnotationsInType);
}
-
+
return false;
}
/**
- * 检查注解是否属于 jakarta.validation 注解
+ * 检查注解是否属于 jakarta.validation 注解。
*
* @param annotation 要检查的注解 {@link Annotation}
- * @return 如果属于 jakarta.validation 注解则返回 true,否则返回 false
+ * @return 如果属于 jakarta.validation 注解则返回 true,否则返回 false {@code boolean}。
*/
private boolean isJakartaConstraintAnnotation(Annotation annotation) {
- // @Valid 注解检查
- if("jakarta.validation.Valid".equals(annotation.annotationType().getName())){
+ // @Valid 注解检查。
+ if ("jakarta.validation.Valid".equals(annotation.annotationType().getName())) {
return true;
}
- // jakarta.validation.constraints, org.hibernate.validator.constraints 包下的注解检查
- // 通过 Constraint 注解检查当前注解是否为校验注解
+ // jakarta.validation.constraints, org.hibernate.validator.constraints 包下的注解检查。
+ // 通过 Constraint 注解检查当前注解是否为校验注解。
Annotation[] metaAnnotations = annotation.annotationType().getAnnotations();
- return Arrays.stream(metaAnnotations)
- .anyMatch(metaAnnotation -> {
- String packageName = metaAnnotation.annotationType().getPackage().getName();
- String className = metaAnnotation.annotationType().getSimpleName();
- return "jakarta.validation".equals(packageName) && "Constraint".equals(className);
- });
+ return Arrays.stream(metaAnnotations).anyMatch(metaAnnotation -> {
+ String packageName = metaAnnotation.annotationType().getPackage().getName();
+ String className = metaAnnotation.annotationType().getSimpleName();
+ return "jakarta.validation".equals(packageName) && "Constraint".equals(className);
+ });
}
}
diff --git a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationDataControllerTest.java b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationDataControllerTest.java
index 614a21be3..ce817a706 100644
--- a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationDataControllerTest.java
+++ b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationDataControllerTest.java
@@ -6,6 +6,8 @@
package modelengine.fitframework.validation;
+import static org.assertj.core.api.Assertions.assertThat;
+
import modelengine.fit.http.client.HttpClassicClientResponse;
import modelengine.fitframework.annotation.Fit;
import modelengine.fitframework.test.annotation.MvcTest;
@@ -15,6 +17,7 @@
import modelengine.fitframework.validation.data.Company;
import modelengine.fitframework.validation.data.Employee;
import modelengine.fitframework.validation.data.ValidationDataController;
+
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -22,8 +25,6 @@
import java.io.IOException;
import java.util.Collections;
-import static org.assertj.core.api.Assertions.assertThat;
-
/**
* {@link ValidationDataController} 的测试集。
*
@@ -50,8 +51,9 @@ void teardown() throws IOException {
void shouldOKWhenCreateValidCompany() {
Employee validEmployee = new Employee("John", 25);
Company validCompany = new Company(Collections.singletonList(validEmployee));
- MockRequestBuilder requestBuilder =
- MockMvcRequestBuilders.post("/validation/company/default").jsonEntity(validCompany).responseType(Void.class);
+ MockRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/validation/company/default")
+ .jsonEntity(validCompany)
+ .responseType(Void.class);
this.response = this.mockMvc.perform(requestBuilder);
assertThat(this.response.statusCode()).isEqualTo(200);
}
@@ -60,8 +62,9 @@ void shouldOKWhenCreateValidCompany() {
@DisplayName("不合法 Company 对象校验")
void shouldFailedWhenCreateInvalidCompany() {
Company invalidCompany = new Company(null);
- MockRequestBuilder requestBuilder =
- MockMvcRequestBuilders.post("/validation/company/default").jsonEntity(invalidCompany).responseType(Void.class);
+ MockRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/validation/company/default")
+ .jsonEntity(invalidCompany)
+ .responseType(Void.class);
this.response = this.mockMvc.perform(requestBuilder);
assertThat(this.response.statusCode()).isEqualTo(500);
}
@@ -71,8 +74,9 @@ void shouldFailedWhenCreateInvalidCompany() {
void shouldOKWhenCreateValidCompanyWithGroup() {
Employee validEmployee = new Employee("Jane", 30);
Company validCompany = new Company(Collections.singletonList(validEmployee));
- MockRequestBuilder requestBuilder =
- MockMvcRequestBuilders.post("/validation/company/companyGroup").jsonEntity(validCompany).responseType(Void.class);
+ MockRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/validation/company/companyGroup")
+ .jsonEntity(validCompany)
+ .responseType(Void.class);
this.response = this.mockMvc.perform(requestBuilder);
assertThat(this.response.statusCode()).isEqualTo(200);
}
@@ -82,8 +86,9 @@ void shouldOKWhenCreateValidCompanyWithGroup() {
void shouldFailedWhenCreateInvalidCompanyWithGroup() {
Employee invalidEmployee = new Employee("", 15);
Company invalidCompany = new Company(Collections.singletonList(invalidEmployee));
- MockRequestBuilder requestBuilder =
- MockMvcRequestBuilders.post("/validation/company/companyGroup").jsonEntity(invalidCompany).responseType(Void.class);
+ MockRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/validation/company/companyGroup")
+ .jsonEntity(invalidCompany)
+ .responseType(Void.class);
this.response = this.mockMvc.perform(requestBuilder);
assertThat(this.response.statusCode()).isEqualTo(500);
}
diff --git a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationHandlerTest.java b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationHandlerTest.java
index 45b51c3db..aafc8b33a 100644
--- a/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationHandlerTest.java
+++ b/framework/fit/java/fit-builtin/plugins/fit-validation-hibernate-jakarta/src/test/java/modelengine/fitframework/validation/ValidationHandlerTest.java
@@ -8,6 +8,7 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import jakarta.validation.ConstraintViolationException;
import modelengine.fitframework.annotation.Fit;
import modelengine.fitframework.test.annotation.FitTestWithJunit;
import modelengine.fitframework.validation.data.Company;
@@ -27,8 +28,6 @@
import java.util.List;
import java.util.Map;
-import jakarta.validation.ConstraintViolationException;
-
/**
* {@link ValidationHandler} 的单元测试。
*
@@ -37,11 +36,8 @@
*/
@DisplayName("测试注解校验功能")
@FitTestWithJunit(includeClasses = {
- ValidateService.class,
- ValidationHandler.class,
- GroupValidateService.StudentValidateService.class,
- GroupValidateService.TeacherValidateService.class,
- GroupValidateService.AdvancedValidateService.class
+ ValidateService.class, ValidationHandler.class, GroupValidateService.StudentValidateService.class,
+ GroupValidateService.TeacherValidateService.class, GroupValidateService.AdvancedValidateService.class
})
public class ValidationHandlerTest {
@Fit
@@ -73,184 +69,161 @@ void giveNestedClassThenValidateOk() {
@Test
@DisplayName("测试@NotNull注解")
void testNotNullValidation() {
- assertThatThrownBy(() -> this.validateService.testNotNull(null))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNotNull(null)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("不能为null");
}
@Test
@DisplayName("测试@NotEmpty注解")
void testNotEmptyValidation() {
- assertThatThrownBy(() -> this.validateService.testNotEmpty(""))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNotEmpty("")).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("不能为空");
}
@Test
@DisplayName("测试@NotBlank注解")
void testNotBlankValidation() {
- assertThatThrownBy(() -> this.validateService.testNotBlank(" "))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNotBlank(" ")).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("不能为空");
}
@Test
@DisplayName("测试@Null注解")
void testNullValidation() {
- assertThatThrownBy(() -> this.validateService.testNull("not null"))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNull("not null")).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须为null");
}
@Test
@DisplayName("测试@Size注解-字符串")
void testSizeStringValidation() {
- assertThatThrownBy(() -> this.validateService.testSize("a"))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testSize("a")).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("个数必须在2和10之间");
}
@Test
@DisplayName("测试@Size注解-集合")
void testSizeListValidation() {
- assertThatThrownBy(() -> this.validateService.testSizeList(Arrays.asList("1", "2", "3", "4")))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("个数必须在1和3之间");
+ assertThatThrownBy(() -> this.validateService.testSizeList(Arrays.asList("1", "2", "3", "4"))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("个数必须在1和3之间");
}
@Test
@DisplayName("测试@Min注解")
void testMinValidation() {
- assertThatThrownBy(() -> this.validateService.testMin(5))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testMin(5)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("最小不能小于10");
}
@Test
@DisplayName("测试@Max注解")
void testMaxValidation() {
- assertThatThrownBy(() -> this.validateService.testMax(150))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testMax(150)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("最大不能超过100");
}
@Test
@DisplayName("测试@DecimalMin注解")
void testDecimalMinValidation() {
- assertThatThrownBy(() -> this.validateService.testDecimalMin(new BigDecimal("5.0")))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("必须大于");
+ assertThatThrownBy(() -> this.validateService.testDecimalMin(new BigDecimal("5.0"))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("必须大于");
}
@Test
@DisplayName("测试@DecimalMax注解")
void testDecimalMaxValidation() {
- assertThatThrownBy(() -> this.validateService.testDecimalMax(new BigDecimal("150.0")))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("必须小于");
+ assertThatThrownBy(() -> this.validateService.testDecimalMax(new BigDecimal("150.0"))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("必须小于");
}
@Test
@DisplayName("测试@Positive注解")
void testPositiveValidation() {
- assertThatThrownBy(() -> this.validateService.testPositive(0))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testPositive(0)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须是正数");
}
@Test
@DisplayName("测试@PositiveOrZero注解")
void testPositiveOrZeroValidation() {
- assertThatThrownBy(() -> this.validateService.testPositiveOrZero(-1))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testPositiveOrZero(-1)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须是正数或零");
}
@Test
@DisplayName("测试@Negative注解")
void testNegativeValidation() {
- assertThatThrownBy(() -> this.validateService.testNegative(1))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNegative(1)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须是负数");
}
@Test
@DisplayName("测试@NegativeOrZero注解")
void testNegativeOrZeroValidation() {
- assertThatThrownBy(() -> this.validateService.testNegativeOrZero(1))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testNegativeOrZero(1)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须是负数或零");
}
@Test
@DisplayName("测试@Digits注解")
void testDigitsValidation() {
- assertThatThrownBy(() -> this.validateService.testDigits(new BigDecimal("1234.567")))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("数字的值超出了允许范围");
+ assertThatThrownBy(() -> this.validateService.testDigits(new BigDecimal("1234.567"))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("数字的值超出了允许范围");
}
@Test
@DisplayName("测试@Past注解")
void testPastValidation() {
- assertThatThrownBy(() -> this.validateService.testPast(LocalDate.now().plusDays(1)))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("需要是一个过去的时间");
+ assertThatThrownBy(() -> this.validateService.testPast(LocalDate.now().plusDays(1))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("需要是一个过去的时间");
}
@Test
@DisplayName("测试@PastOrPresent注解")
void testPastOrPresentValidation() {
- assertThatThrownBy(() -> this.validateService.testPastOrPresent(LocalDate.now().plusDays(1)))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("需要是一个过去或现在的时间");
+ assertThatThrownBy(() -> this.validateService.testPastOrPresent(LocalDate.now().plusDays(1))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("需要是一个过去或现在的时间");
}
@Test
@DisplayName("测试@Future注解")
void testFutureValidation() {
- assertThatThrownBy(() -> this.validateService.testFuture(LocalDate.now().minusDays(1)))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("需要是一个将来的时间");
+ assertThatThrownBy(() -> this.validateService.testFuture(LocalDate.now().minusDays(1))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("需要是一个将来的时间");
}
@Test
@DisplayName("测试@FutureOrPresent注解")
void testFutureOrPresentValidation() {
- assertThatThrownBy(() -> this.validateService.testFutureOrPresent(LocalDate.now().minusDays(1)))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("需要是一个将来或现在的时间");
+ assertThatThrownBy(() -> this.validateService.testFutureOrPresent(LocalDate.now().minusDays(1))).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("需要是一个将来或现在的时间");
}
@Test
@DisplayName("测试@Pattern注解")
void testPatternValidation() {
- assertThatThrownBy(() -> this.validateService.testPattern("123"))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testPattern("123")).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("需要匹配正则表达式");
}
@Test
@DisplayName("测试@Email注解")
void testEmailValidation() {
- assertThatThrownBy(() -> this.validateService.testEmail("invalid-email"))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("不是一个合法的电子邮件地址");
+ assertThatThrownBy(() -> this.validateService.testEmail("invalid-email")).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("不是一个合法的电子邮件地址");
}
@Test
@DisplayName("测试@AssertTrue注解")
void testAssertTrueValidation() {
- assertThatThrownBy(() -> this.validateService.testAssertTrue(false))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testAssertTrue(false)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("只能为true");
}
@Test
@DisplayName("测试@AssertFalse注解")
void testAssertFalseValidation() {
- assertThatThrownBy(() -> this.validateService.testAssertFalse(true))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> this.validateService.testAssertFalse(true)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("只能为false");
}
@@ -260,34 +233,31 @@ void testComplexObjectValidation() {
ValidationTestData invalidData = new ValidationTestData();
invalidData.setName(null); // 违反@NotNull
invalidData.setAge(200); // 违反@Max(150)
-
- assertThatThrownBy(() -> this.validateService.testValidObject(invalidData))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("名称不能为空");
+
+ assertThatThrownBy(() -> this.validateService.testValidObject(invalidData)).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("名称不能为空");
}
@Test
@DisplayName("校验数据类,该数据类的 Constraint 字段会被校验,其余字段不会被校验")
public void givenFieldsWithConstraintAnnotationThenValidateHappened() {
Employee invalidEmployee = new Employee("", 150); // 空名字,年龄超限
- assertThatThrownBy(() -> validateService.validateEmployee(invalidEmployee))
- .isInstanceOf(ConstraintViolationException.class)
- .hasMessageContaining("不能为空");
+ assertThatThrownBy(() -> validateService.validateEmployee(invalidEmployee)).isInstanceOf(
+ ConstraintViolationException.class).hasMessageContaining("不能为空");
}
@Test
@DisplayName("校验方法参数,该方法的 Constraint 参数会被校验,其余参数不会被校验")
public void givenParametersWithConstraintAnnotationThenValidateHappened() {
- assertThatThrownBy(() -> validateService.validateAge(-1))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> validateService.validateAge(-1)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("必须是正数");
}
@Test
@DisplayName("校验多个参数")
public void givenMultipleParametersThenValidateHappened() {
- assertThatThrownBy(() -> validateService.validateNameAndAge("", -1))
- .isInstanceOf(ConstraintViolationException.class);
+ assertThatThrownBy(() -> validateService.validateNameAndAge("",
+ -1)).isInstanceOf(ConstraintViolationException.class);
}
@Test
@@ -296,9 +266,8 @@ public void givenFieldsThenSameGroupValidateHappened() {
ValidationTestData data = new ValidationTestData();
data.setAge(300); // 违反高级分组的约束
data.setName(""); // 违反默认分组约束
-
- assertThatThrownBy(() -> validateService.validateAdvancedGroup(data))
- .isInstanceOf(ConstraintViolationException.class)
+
+ assertThatThrownBy(() -> validateService.validateAdvancedGroup(data)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("高级组年龄必须小于等于200");
}
@@ -306,8 +275,7 @@ public void givenFieldsThenSameGroupValidateHappened() {
@DisplayName("校验方法参数,分组约束测试")
public void givenParametersThenGroupValidateHappened() {
// 测试学生年龄验证 - 现在会抛出异常,因为使用了学生分组
- assertThatThrownBy(() -> validateService.validateStudentAge(25))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> validateService.validateStudentAge(25)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("范围要在7~20之内");
}
@@ -315,8 +283,7 @@ public void givenParametersThenGroupValidateHappened() {
@DisplayName("校验方法参数,教师年龄验证测试")
public void givenParametersThenTeacherGroupValidateNotHappened() {
// 测试教师年龄验证 - 现在会抛出异常,因为使用了教师分组
- assertThatThrownBy(() -> validateService.validateTeacherAge(15))
- .isInstanceOf(ConstraintViolationException.class)
+ assertThatThrownBy(() -> validateService.validateTeacherAge(15)).isInstanceOf(ConstraintViolationException.class)
.hasMessageContaining("范围要在22~65之内");
}
@@ -326,9 +293,8 @@ void shouldReturnMsgWhenValidateCompany() {
Employee invalidEmployee1 = new Employee("", 17); // 空名字,年龄不足
Employee invalidEmployee2 = new Employee("John", 150); // 年龄超限
Company company = new Company(Arrays.asList(invalidEmployee1, invalidEmployee2));
-
- assertThatThrownBy(() -> validateService.validateCompany(company))
- .isInstanceOf(ConstraintViolationException.class);
+
+ assertThatThrownBy(() -> validateService.validateCompany(company)).isInstanceOf(ConstraintViolationException.class);
}
@Test
@@ -338,9 +304,9 @@ void shouldReturnMsgWhenValidateList() {
Employee invalidEmployee1 = new Employee("", 17);
Employee invalidEmployee2 = new Employee("Jane", 150);
List