2011-02-23 133 views
2

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我錯過了協助單元測試的限制。

回答

3

您可以查看用於Hibernate Validator自己的測試的類org.hibernate.validator.test.util.TestUtil,並提供用於測試預期約束違規的功能(其中包括例如assertCorrectConstraintTypes())。

請注意,這個類不是Hibernate Validator的公共API的一部分,所以最好只用它來獲得一些想法。

比較錯誤消息時,務必確保VM的語言環境正確設置。更好的辦法是與通過正確的資源包加載的本地化消息進行匹配(對於Hibernate驗證程序,標準約束爲org.hibernate.validator.ValidationMessages)。

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"); 
     } 
    } 
}