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我缺少协助单元测试约束。
答案 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");
}
}
}