diff --git a/backend/src/main/java/com/xly/test4/module/usr/dto/UserCreateDTO.java b/backend/src/main/java/com/xly/test4/module/usr/dto/UserCreateDTO.java new file mode 100644 index 0000000..26f84a8 --- /dev/null +++ b/backend/src/main/java/com/xly/test4/module/usr/dto/UserCreateDTO.java @@ -0,0 +1,39 @@ +package com.xly.test4.module.usr.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +@Data +public class UserCreateDTO { + + @NotBlank(message = "用户号不能为空") + @Size(max = 32, message = "用户号长度不能超过 32") + private String userCode; + + @NotBlank(message = "用户名不能为空") + @Size(max = 50, message = "用户名长度不能超过 50") + private String userName; + + private Integer employeeId; + + @NotBlank(message = "用户类型不能为空") + @Pattern(regexp = "NORMAL|ADMIN", message = "用户类型必须为 NORMAL 或 ADMIN") + private String userType; + + @NotBlank(message = "语言不能为空") + @Pattern(regexp = "zh-CN|en|zh-TW", message = "语言必须为 zh-CN / en / zh-TW") + private String language; + + @NotNull(message = "单据修改权限标志不能为空") + private Boolean canEditDoc; + + @Size(min = 1, max = 64, message = "密码长度需在 1-64 字符之间") + private String password; + + private List permissionIds; +} diff --git a/backend/src/test/java/com/xly/test4/module/usr/dto/UserCreateDTOValidationTest.java b/backend/src/test/java/com/xly/test4/module/usr/dto/UserCreateDTOValidationTest.java new file mode 100644 index 0000000..ada1d54 --- /dev/null +++ b/backend/src/test/java/com/xly/test4/module/usr/dto/UserCreateDTOValidationTest.java @@ -0,0 +1,117 @@ +package com.xly.test4.module.usr.dto; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class UserCreateDTOValidationTest { + + private static ValidatorFactory factory; + private static Validator validator; + + @BeforeAll + static void setUp() { + factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + @AfterAll + static void tearDown() { + factory.close(); + } + + private UserCreateDTO validDTO() { + UserCreateDTO dto = new UserCreateDTO(); + dto.setUserCode("U-001"); + dto.setUserName("alice"); + dto.setEmployeeId(null); + dto.setUserType("NORMAL"); + dto.setLanguage("zh-CN"); + dto.setCanEditDoc(false); + dto.setPassword("Pass1234"); + dto.setPermissionIds(List.of()); + return dto; + } + + @Test + void allRequiredFieldsValid_zeroViolations() { + assertThat(validator.validate(validDTO())).isEmpty(); + } + + @Test + void userNameBlank_violatesNotBlank() { + UserCreateDTO dto = validDTO(); + dto.setUserName(""); + + Set> violations = validator.validate(dto); + assertThat(violations).extracting(v -> v.getPropertyPath().toString()) + .contains("userName"); + } + + @Test + void userTypeOutOfEnum_violatesPattern() { + UserCreateDTO dto = validDTO(); + dto.setUserType("FOO"); + + assertThat(validator.validate(dto)) + .extracting(v -> v.getPropertyPath().toString()) + .contains("userType"); + } + + @Test + void languageOutOfEnum_violatesPattern() { + UserCreateDTO dto = validDTO(); + dto.setLanguage("fr"); + + assertThat(validator.validate(dto)) + .extracting(v -> v.getPropertyPath().toString()) + .contains("language"); + } + + @Test + void userCodeOver32Chars_violatesSize() { + UserCreateDTO dto = validDTO(); + dto.setUserCode("X".repeat(33)); + + assertThat(validator.validate(dto)) + .extracting(v -> v.getPropertyPath().toString()) + .contains("userCode"); + } + + @Test + void canEditDocNull_violatesNotNull() { + UserCreateDTO dto = validDTO(); + dto.setCanEditDoc(null); + + assertThat(validator.validate(dto)) + .extracting(v -> v.getPropertyPath().toString()) + .contains("canEditDoc"); + } + + @Test + void passwordOver64Chars_violatesSize() { + UserCreateDTO dto = validDTO(); + dto.setPassword("p".repeat(65)); + + assertThat(validator.validate(dto)) + .extracting(v -> v.getPropertyPath().toString()) + .contains("password"); + } + + @Test + void passwordNull_isAllowed() { + UserCreateDTO dto = validDTO(); + dto.setPassword(null); + + assertThat(validator.validate(dto)).isEmpty(); + } +}