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

Java 在JSR303Bean验证单元测试中,如何检查违反了哪些约束,java,spring,Java,Spring,我正试图为bean验证编写一个jUnit测试。 我读 并编写了如下的测试代码 我的环境: Sprint Boot 2.2.6 爪哇11 AssertJ 3.15.0 目标Bean类: public class Customer { @NotEmpty private String name; @Min(18) private int age; // getter and setter } JUnit测试代码: public class Cust

我正试图为bean验证编写一个jUnit测试。 我读 并编写了如下的测试代码

我的环境:

  • Sprint Boot 2.2.6
  • 爪哇11
  • 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");
    }
}
公共类CustomerValidationTest{
私有验证器验证器=Validation.buildDefaultValidatorFactory().getValidator();
@试验
公开无效测试(){
客户=新客户(空,18);
设置冲突=验证程序。验证(客户);
assertThat(inflictions.size()).isEqualTo(1);//检查冲突计数
//检查违规消息违反了哪些约束
断言(违规)。提取(“消息”)。仅包含(“不得为空”);
}
}
我想检查违反了哪些约束。现在,我检查违规信息。 有更好的方法吗?

本教程将在第7节中介绍测试。。Validations..”这是一种很好的假设预期冲突是集合的一部分的方法

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

@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"))); }
@Test public void validatingObject(){
汽车=新车();
设置冲突=验证程序。验证(car);
assertThat(inflictions.size()).isEqualTo(1);
断言(违反)
.anyMatch(具有PropertyPath(“CustomerPropertyPath for CarViolation”)
.和(具有消息(“期望违反的消息”);}
本教程将在第7节中介绍测试。。Validations..”这是一种很好的假设预期冲突是集合的一部分的方法

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

@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"))); }
@Test public void validatingObject(){
汽车=新车();
设置冲突=验证程序。验证(car);
assertThat(inflictions.size()).isEqualTo(1);
断言(违反)
.anyMatch(具有PropertyPath(“CustomerPropertyPath for CarViolation”)
.和(具有消息(“期望违反的消息”);}

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

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

但是,在更大的设置中,情况可能并非如此。实际上,您想要做的是断言您预期的违规行为存在

使用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)
    );
公共类CustomerValidationTest{
私有静态验证器;
私营静电加工厂;
@org.junit.jupiter.api.beforeach
无效设置(){
Locale.setDefault(Locale.ENGLISH);//应为英文错误消息
factory=Validation.buildDefaultValidatorFactory();
validator=factory.getValidator();
}
@org.junit.jupiter.api.AfterEach
void tearDown(){
工厂关闭();
}
@org.junit.jupiter.api.Test
public void testContainsEmptyNameViolation(){
客户=新客户(空,18);
//执行验证
设置constraintViolations=validator.validate(客户);
boolean hasExpectedPropertyPath=constraintViolations.stream()
.map(ConstraintViolation::getPropertyPath)
.map(路径::toString)
.anyMatch(“名称”::等于);
boolean hasExpectedViolationMessage=constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.anyMatch(“不得为空”::等于);
资产(
()->assertFalse(constraintViolations.isEmpty()),
()->assertTrue(hasExpectedPropertyPath),
()->assertTrue(hasExpectedViolationMessage)
);

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

在您的小型测试设置中,您可能能够监督是否确实发生了一次违规,并且只发生了一次违规

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

但是,在一个更大的设置中,情况可能并非如此。实际上,您要做的是断言预期的违规行为存在

使用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)
    );
公共类CustomerValidationTest{
私有静态验证器;
私营静电加工厂;
@org.junit.jupiter.api.beforeach
无效设置(){
Locale.setDefault(Locale.ENGLISH);//应为英文错误消息
factory=Validation.buildDefaultValidatorFactory();
validator=factory.getValidator();
}
@org.junit.jupiter.api.AfterEach
void tearDown(){
工厂关闭();
}
@org.junit.jupiter.api.Test
public void testContainsEmptyNameViolation(){
客户=新客户(空,18);
//执行验证
设置constraintViolations=validator.validate(客户);
boolean hasExpectedPropertyPath=constraintViolations.stream()
.map(ConstraintViolation::getPropertyPath)
.map(路径::toString)
.anyMatch(“名称”::等于);
boolean hasExpectedViolationMessage=constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.anyMatch(“不得为空”::等于);
资产(
()->assertFalse(constraintViolations.isEmpty()),
()->assertTrue(hasExpectedPropertyPath),
()->assertTrue(hasExpectedViolationMessage)
);

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

您可以添加一条与字段
@NotEmpty(message=“name应该不为空”)
相关的消息,这将帮助您验证(使用断言)哪个字段违反了约束。您可以添加一条与字段
@NotEmpty(message)相关的消息=“名称不应为空”)
,这将帮助您验证(使用断言)哪个字段违反了约束。