如何用JUnit测试Spring Boot请求模型类的字段验证及toString方法
为Spring Boot请求模型编写JUnit测试用例(满足校验规则+高覆盖率)
前提准备
确保项目依赖包含以下内容(Maven示例):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </dependency>
假设你的请求模型类RequestModel定义如下(带校验注解):
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; public class RequestModel { @NotBlank(message = "id不能为空且长度必须为8") @Size(min = 8, max = 8, message = "id长度必须为8") private String id; @NotNull(message = "revision不能为null") private Integer revision; @NotBlank(message = "state不能为空") @Size(min = 2, max = 2, message = "state长度必须为2") @Pattern(regexp = "^[A-Z]{2}$", message = "state必须为两位大写字母") private String state; // 全参构造器 public RequestModel(String id, Integer revision, String state) { this.id = id; this.revision = revision; this.state = state; } // toString方法(Lombok自动生成或手动编写) @Override public String toString() { return "RequestModel{" + "id='" + id + '\'' + ", revision=" + revision + ", state='" + state + '\'' + '}'; } // getter、setter方法省略 }
测试类实现
创建RequestModelTest类,用JUnit 5 + AssertJ + Bean Validator完成测试:
import org.junit.jupiter.api.Test; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; class RequestModelTest { private final Validator validator; // 初始化校验器 public RequestModelTest() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } // 合法场景:所有字段符合规则,无校验错误 @Test void shouldPassValidationWhenAllFieldsAreValid() { RequestModel validModel = new RequestModel("12345678", 1, "AB"); Set<?> violations = validator.validate(validModel); assertThat(violations).isEmpty(); } // --- Id字段校验测试 --- @Test void shouldFailValidationWhenIdIsNull() { RequestModel model = new RequestModel(null, 1, "AB"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(2); assertThat(violations).extracting("message") .contains("id不能为空且长度必须为8", "id长度必须为8"); } @Test void shouldFailValidationWhenIdIsEmpty() { RequestModel model = new RequestModel("", 1, "AB"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(2); assertThat(violations).extracting("message") .contains("id不能为空且长度必须为8", "id长度必须为8"); } @Test void shouldFailValidationWhenIdLengthIsLessThan8() { RequestModel model = new RequestModel("1234567", 1, "AB"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(1); assertThat(violations).extracting("message") .contains("id长度必须为8"); } @Test void shouldFailValidationWhenIdLengthIsMoreThan8() { RequestModel model = new RequestModel("123456789", 1, "AB"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(1); assertThat(violations).extracting("message") .contains("id长度必须为8"); } // --- Revision字段校验测试 --- @Test void shouldFailValidationWhenRevisionIsNull() { RequestModel model = new RequestModel("12345678", null, "AB"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(1); assertThat(violations).extracting("message") .contains("revision不能为null"); } // --- State字段校验测试 --- @Test void shouldFailValidationWhenStateIsNull() { RequestModel model = new RequestModel("12345678", 1, null); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(3); assertThat(violations).extracting("message") .contains("state不能为空", "state长度必须为2", "state必须为两位大写字母"); } @Test void shouldFailValidationWhenStateIsEmpty() { RequestModel model = new RequestModel("12345678", 1, ""); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(3); assertThat(violations).extracting("message") .contains("state不能为空", "state长度必须为2", "state必须为两位大写字母"); } @Test void shouldFailValidationWhenStateLengthIsNot2() { RequestModel model = new RequestModel("12345678", 1, "A"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(2); assertThat(violations).extracting("message") .contains("state长度必须为2", "state必须为两位大写字母"); } @Test void shouldFailValidationWhenStateDoesNotMatchRegex() { RequestModel model = new RequestModel("12345678", 1, "ab"); Set<?> violations = validator.validate(model); assertThat(violations).hasSize(1); assertThat(violations).extracting("message") .contains("state必须为两位大写字母"); } // --- toString方法测试 --- @Test void shouldReturnCorrectToStringValue() { RequestModel model = new RequestModel("12345678", 1, "AB"); String toStringResult = model.toString(); assertThat(toStringResult) .contains("id='12345678'") .contains("revision=1") .contains("state='AB'") .startsWith("RequestModel{") .endsWith("}"); } }
覆盖率说明
以上测试覆盖了:
- 所有字段的合法/非法校验场景,覆盖了校验注解的全部分支逻辑
toString方法的输出验证- 模型类的构造器逻辑
运行测试后,代码覆盖率会轻松超过90%;如果模型类包含Lombok生成的getter/setter,可在测试中调用这些方法(比如assertThat(model.getId()).isEqualTo("12345678"))进一步提升覆盖率。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

