在JSR 303 bean验证单元测试中,如何检查违反了哪些约束

时间:2020-05-06 13:32:27

标签: java spring

我正在尝试编写一个jUnit测试来进行bean验证。 我读了How to test validation annotations of a class using JUnit? 并编写了如下的测试代码。

我的环境:

  • Sprint Boot 2.2.6
  • Java11
  • AssertJ 3.15.0

目标Bean类:

public class Customer {

    @NotEmpty
    private String name;

    @Min(18)
    private int age;

    // getter and setter
}

JUnit测试代码:

public class CustomerValidationTest {
    private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    @Test
    public void test() {

        Customer customer = new Customer(null, 18);

        Set<ConstraintViolation<Customer>> violations = validator.validate(customer);
        assertThat(violations.size()).isEqualTo(1); // check violations count

        // check which constraints are violated by the message of the violation
        assertThat(violations).extracting("message").containsOnly("must not be empty");
    }
}

我想检查违反了哪些约束。现在,我检查违规消息。 有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

本教程 here 在第 7 节“测试..验证..”中展示了一种假设预期违规是集合的一部分的好方法。

根据您的测试框架,这可能是一个可以遵循的策略。

@Test public void validatingObject() {
    Car car = new Car();
    Set<ConstraintViolation> violations = validator.validate(car);
    assertThat(violations.size()).isEqualTo(1);

    assertThat(violations)
      .anyMatch(havingPropertyPath("customerPropertyPathForCarViolation")
      .and(havingMessage("message of desired violation"))); }

答案 1 :(得分:0)

在您的小型测试设置中,您可能能够监督是否准确且仅发生一次违规。

assertThat(violations.size()).isEqualTo(1);

.containsOnly("must not be empty")

然而,在更大的设置中,情况可能并非如此。您真正想要做的是断言您的预期违规行为存在。

使用 Testframework junit-jupiter-api:5.6.2 我做了这样的测试:

public class CustomerValidationTest {
private static Validator validator;
private static ValidatorFactory factory;

@org.junit.jupiter.api.BeforeEach
void setUp() {
    Locale.setDefault(Locale.ENGLISH);  //expecting english error messages
    factory = Validation.buildDefaultValidatorFactory();
    validator = factory.getValidator();
}

@org.junit.jupiter.api.AfterEach
void tearDown() {
    factory.close();
}

@org.junit.jupiter.api.Test
public void testContainsEmptyNameViolation() {

    Customer customer = new Customer(null, 18);

    //perform validation
    Set<ConstraintViolation<Customer>> constraintViolations = validator.validate(customer);

    boolean hasExpectedPropertyPath = constraintViolations.stream()
            .map(ConstraintViolation::getPropertyPath)
            .map(Path::toString)
            .anyMatch("name"::equals);
    boolean hasExpectedViolationMessage = constraintViolations.stream()
            .map(ConstraintViolation::getMessage)
            .anyMatch("must not be empty"::equals);

    assertAll(
            () -> assertFalse(constraintViolations.isEmpty()),
            () -> assertTrue(hasExpectedPropertyPath),
            () -> assertTrue(hasExpectedViolationMessage)
    );

即使您要求使用 AssertJ,我希望这仍然对您有所帮助。