Skip to content

Instantly share code, notes, and snippets.

@jangalinski
Created April 11, 2013 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jangalinski/5361920 to your computer and use it in GitHub Desktop.
Save jangalinski/5361920 to your computer and use it in GitHub Desktop.
Useful little junit-4.11 classrule that allows to assertValid() directly without looking into the validation result set every time, but still can be used as a full blown JSR303 validator if needed.
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.assertThat;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.metadata.BeanDescriptor;
import org.apache.commons.lang3.builder.Builder;
import org.apache.log4j.Logger;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.junit.rules.TestWatcher;
/**
* JUnit Rule for Bean Validation Tests. Allows to assertValid/assrtNotValid instead of looking into the Set of
* {@link ConstraintViolation} after every validation.
* <p/>
* Since this is a Singleton Rule, use it as a @ClassRule:
*
* <pre>
*
* &#064;ClassRule
* public static BeanValidationRule VALIDATOR = BeanValidationRule.INSTANCE;
*
* </pre>
* <p/>
* If the assertValid()-ASsertions dont fit your needs, the rule implements the Validator interface, so you can use all
* JSR303 methods directly.
*
* @author Jan Galinski, Holisticon AG
*/
public final class BeanValidationRule extends TestWatcher implements Validator {
private final Logger logger = Logger.getLogger(BeanValidationRule.class);
/**
* JSR303 Validator used for all assertions.
*/
private final Validator validator;
/**
* Singleton Instance of this Rule. Since we only use the default validator with fixed config, we do not need to
* set up a new instance every time.
*/
public static final BeanValidationRule INSTANCE = new BeanValidationRule();
/**
* Use the Singleton {@link BeanValidationRule#INSTANCE} instance.
* <p />
* Initialises the validator.
*/
private BeanValidationRule() {
final HibernateValidatorConfiguration configuration = Validation.byProvider(HibernateValidator.class).configure();
final ValidatorFactory factory = configuration
.failFast(true)
.buildValidatorFactory();
this.validator = factory.getValidator();
}
/**
* Fails when {@link Validator#validate(Object, Class...)} returns a non empty set.
*
* @param bean validated object
* @param <T> type of bean
*/
public static <T> void assertValid(final T bean) {
assertThat(INSTANCE.validate(bean), is(empty()));
}
/**
* Delegates to {@link #assertValid(Object)}.
*
* @param builder builder that creates the bean to be validated.
* @param <T> type of bean
*/
public static <T> void assertValid(final Builder<T> builder) {
assertValid(builder.build());
}
/**
* Validate only one specified property.
* Fails when {@link Validator#validateProperty(Object, String, Class...)} returns a non empty set.
*
* @param bean the object under validation
* @param property the attribute to be validated
* @param <T> type of bean
*/
public static <T> void assertValid(final T bean, final String property) {
assertThat(INSTANCE.validateProperty(bean, property), is(empty()));
}
/**
* Delegates to {@link #assertValid(Object, String)}.
*
* @param builder builder that creates the bean to validate
* @param property the attribute to validate
* @param <T> type of bean
*/
public static <T> void assertValid(final Builder<T> builder, final String property) {
assertValid(builder.build(), property);
}
/**
* Like {@link #assertValid(Object)} but fails if validation result is NOT empty.
*
* @param bean the object under validation
* @param <T> type of bean
*/
public static <T> void assertNotValid(final T bean) {
assertThat(INSTANCE.validate(bean), not(empty()));
}
/**
* Like {@link #assertValid(Builder)} but fails if validation result is NOT empty.
*
* @param builder builder that creats the bean to validate
* @param <T> type of bean
*/
public static <T> void assertNotValid(final Builder<T> builder) {
assertNotValid(builder.build());
}
/**
* Like {@link #assertValid(Object, String)} but fails if validation result is NOT empty.
*
* @param bean the object under validation
* @param property the attribute to validate
* @param <T> type of bean
*/
public static <T> void assertNotValid(final T bean, final String property) {
assertThat(INSTANCE.validateProperty(bean, property), not(empty()));
}
/**
* Like {@link #assertValid(Builder, String)} but fails if validation result is NOT empty.
*
* @param builder builder that creates the bean to validate
* @param property the attribute to validate
* @param <T> type of bean
*/
public static <T> void assertNotValid(final Builder<T> builder, final String property) {
assertNotValid(builder.build(), property);
}
@Override
public BeanDescriptor getConstraintsForClass(final Class<?> beanType) {
return validator.getConstraintsForClass(beanType);
}
@Override
public <T> T unwrap(final Class<T> beanType) {
return validator.unwrap(beanType);
}
@Override
public <T> Set<ConstraintViolation<T>> validate(final T bean, final Class<?>... groups) {
final Set<ConstraintViolation<T>> result = validator.validate(bean, groups);
debug(result);
return result;
}
@Override
public <T> Set<ConstraintViolation<T>> validateProperty(final T bean, final String propertyName,
final Class<?>... groups) {
final Set<ConstraintViolation<T>> result = validator.validateProperty(bean, propertyName, groups);
debug(result);
return result;
}
@Override
public <T> Set<ConstraintViolation<T>> validateValue(final Class<T> beanType, final String propertyName,
final Object value,
final Class<?>... groups) {
return validator.validateValue(beanType, propertyName, value, groups);
}
/**
* Delegates to {@link Logger#debug(Object)}.
*
* @param violations validation messages to log
* @param <T> type of bean
*/
private <T> void debug(final Set<ConstraintViolation<T>> violations) {
if (!violations.isEmpty() && logger.isDebugEnabled()) {
logger.debug(violations);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment