1

Hibernate Validator 文档有一个简单的入门指南,其中概述了测试验证规则

相关的块是

@Test
public void manufacturerIsNull() {
    Car car = new Car(null, "DD-AB-123", 4);

    Set<ConstraintViolation<Car>> constraintViolations =
        validator.validate(car);

    assertEquals(1, constraintViolations.size());
    assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
}

在我看来,测试 NotNull 约束是否被违反是一条相当模糊的路线。

我的简单解决方案类似于

public static <T> boolean  containsConstraintViolation(
    Set<ConstraintViolation<T>> violations, Class<?> constraint) {

    for (ConstraintViolation<?> violation : violations) {
        ConstraintDescriptor<?> descriptor = violation.getConstraintDescriptor();
            if (constraint.isAssignableFrom(descriptor.getAnnotation().getClass()))
                return true;
        }
    return false;
}

这让我可以做类似的测试

assertTrue(ValidationUtils.containsConstraintViolation(violations, NotNull.class));

但是,我确信从长远来看这将是幼稚的,并且我想知道是否没有其他库或 API 可以帮助进行单元测试约束。

4

2 回答 2

2

您可以查看org.hibernate.validator.test.util.TestUtil用于 Hibernate Validator 自己的测试的类,并提供用于测试预期约束违规的功能(其中包括assertCorrectConstraintTypes()例如)。

请注意,这个类不是 Hibernate Validator 的公共 API 的一部分,所以最好只是使用它来获得一些想法。

比较错误消息时,请务必正确设置 VM 的区域设置。更好的是匹配通过正确资源包加载的本地化消息(org.hibernate.validator.ValidationMessages对于 Hibernate Validator 的标准约束)。

于 2011-05-28T15:31:46.743 回答
1

针对具体约束类测试 bean 验证是一个坏主意,因为它将测试与实现紧密耦合。所以,而不是这个:

assertTrue(ValidationUtils.containsConstraintViolation(violations, NotNull.class));

您可以测试验证的结果是否符合您的预期:

assertThat(validationFor(car, onField("manufacturer")), fails());

所以你的测试会变成这样

@Test
public void car_with_null_manufacturer_is_invalid() {
    Car car = new Car(null, "DD-AB-123", 4);

    assertThat(validationFor(car, onField("manufacturer")), fails());
}

提供匹配器的实用程序类是

public class HibernateValidationUtils {
    private static Validator VALIDATOR;
    static {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        VALIDATOR = factory.getValidator();
    }

    public static Set<ConstraintViolation<Object>> validationFor(Object object, String fieldname) {
        return VALIDATOR.validateProperty(object, fieldname);
    }

    public static String onField(String fieldname) {
        return fieldname;
    }

    public static Matcher<Set<ConstraintViolation<Object>>> succedes() {
        return new PassesValidation();
    }

    public static Matcher<Set<ConstraintViolation<Object>>> fails() {
        return new Not(new PassesValidation());
    }

    static class PassesValidation extends BaseMatcher<Set<ConstraintViolation<Object>>> {
        @Override
        public boolean matches(Object o) {
            boolean result = false;
            if (o instanceof Set) {
                result = ((Set) o).isEmpty();
            }
            return result;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("valid");
        }
    }
}
于 2014-04-07T10:21:46.343 回答