diff --git a/src/main/java/com/yunhai/userbase/model/application/ApplicationInfoRequest.java b/src/main/java/com/yunhai/userbase/model/application/ApplicationInfoRequest.java index db3c4c0..3e0167b 100644 --- a/src/main/java/com/yunhai/userbase/model/application/ApplicationInfoRequest.java +++ b/src/main/java/com/yunhai/userbase/model/application/ApplicationInfoRequest.java @@ -36,18 +36,18 @@ public class ApplicationInfoRequest { private Integer categoryId; /** - * 技术标识(= projman app.name,如 notice),全库唯一,新增必填。
- * 编辑不强制(部分提交场景不回传则保持原值);值域为引用键,改名须盘点引用。 + * 技术标识(= projman app.name,如 notice),全库唯一,新增与编辑均必填。
+ * 编辑必填(2026-09-28 拍板):app_code 是应用身份锚点(消息 jump_app/服务目录键),不许置空; + * 存量 null 历史行不追溯,但编辑提交时必须补填。值域为引用键,改名须盘点引用。 */ - @NotBlank(groups = ValidationGroups.Create.class, message = "技术标识不能为空") + @NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "技术标识不能为空") @Size(max = 32, message = "技术标识长度不能超过32") private String appCode; /** - * 应用性质:BASE=基石 / BUSINESS=业务,新增必填。
- * 编辑不强制(不回传则保持原值);学校模式覆盖线不涉及本字段。 + * 应用性质:BASE=基石 / BUSINESS=业务,新增与编辑均必填(2026-09-28 拍板,存量 null 行不追溯)。 */ - @NotBlank(groups = ValidationGroups.Create.class, message = "应用性质不能为空") + @NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "应用性质不能为空") @Size(max = 16, message = "应用性质长度不能超过16") private String appNature; diff --git a/src/test/java/com/yunhai/userbase/model/application/ApplicationInfoRequestValidationTest.java b/src/test/java/com/yunhai/userbase/model/application/ApplicationInfoRequestValidationTest.java new file mode 100644 index 0000000..98c8410 --- /dev/null +++ b/src/test/java/com/yunhai/userbase/model/application/ApplicationInfoRequestValidationTest.java @@ -0,0 +1,83 @@ +package com.yunhai.userbase.model.application; + +import com.yunhai.userbase.common.validation.ValidationGroups; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * app_code / app_nature 编辑必填校验组单测(消息方案 C5,2026-09-28 拍板:新增/编辑均必填, + * 存量 null 历史行不追溯)。Create 组此前已必填;本测试冻结 Update 组同口径—— + * 编辑提交置空 → 校验失败;带值 → 通过。学校模式覆盖线由前端分支原样回传原值满足校验 + * (后端 editAppForSchool 只读 name/desc/pcIcon,其余字段忽略)。 + */ +@DisplayName("ApplicationInfoRequest - app_code/app_nature 新增与编辑均必填") +class ApplicationInfoRequestValidationTest { + + private static Validator validator; + + @BeforeAll + static void setUp() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + private ApplicationInfoRequest validRequest() { + ApplicationInfoRequest request = new ApplicationInfoRequest(); + request.setId(100011); + request.setName("流程中心"); + request.setCategoryId(2); + request.setAppCode("flow-center"); + request.setAppNature("BUSINESS"); + return request; + } + + private static boolean hasViolation(Set> violations, String field) { + return violations.stream().anyMatch(v -> v.getPropertyPath().toString().equals(field)); + } + + @Test + void edit_空appCode_校验失败() { + ApplicationInfoRequest request = validRequest(); + request.setAppCode(" "); + Set> violations = + validator.validate(request, ValidationGroups.Update.class); + assertTrue(hasViolation(violations, "appCode"), "编辑时技术标识置空必须被 Update 组拦截"); + } + + @Test + void edit_空appNature_校验失败() { + ApplicationInfoRequest request = validRequest(); + request.setAppNature(null); + Set> violations = + validator.validate(request, ValidationGroups.Update.class); + assertTrue(hasViolation(violations, "appNature"), "编辑时应用性质置空必须被 Update 组拦截"); + } + + @Test + void edit_带appCodeAppNature_通过() { + Set> violations = + validator.validate(validRequest(), ValidationGroups.Update.class); + assertFalse(hasViolation(violations, "appCode")); + assertFalse(hasViolation(violations, "appNature")); + } + + @Test + void create_空appCode_校验失败_口径不变() { + ApplicationInfoRequest request = validRequest(); + request.setId(null); + request.setAppCode(null); + Set> violations = + validator.validate(request, ValidationGroups.Create.class); + assertTrue(hasViolation(violations, "appCode"), "新增必填为既有口径,防回归"); + } +}