测试验证约束

时间:2011-02-23 18:09:26

标签: java validation junit hibernate-validator

Hibernate Validator文档有一个简单的入门指南,其中概述了testing validation rules

相关的块是

@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我缺少协助单元测试约束。

2 个答案:

答案 0 :(得分:3)

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

请注意,此类不是Hibernate Validator的公共API的一部分,因此最好只使用它来获取一些想法。

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

答案 1 :(得分: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");
        }
    }
}