blob: 7ad37ee077b99ef06901dcb558d03ad08f36a2f2 [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.validation.testing.constraints;
import junit.framework.TestCase;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* TestCase for {@link javax.validation.ConstraintValidator}s.
* <p>
* Subclasses must :
* <ul>
* <li>implement {@link #getAnnotationClass()}</li>
* <li>implement {@link #createValidator()}.</li>
* <li>define a field called <code>defaultField</code> and annotate it with the
* constraint Annotation under test</li>
* </ul>
*
* <p>
* If additional instances of the annotation need to be tested you can get there
* value with {@link #getAnnotation(Class, Class, String)}
*
* @param <A> The constraint Annotation of the ConstraintValidator under test
* @param <T> The bean type of the ConstraintValidator under test
*/
public abstract class ConstraintValidatorTestCase<A extends Annotation, T>
extends TestCase {
public final static String DEFAULT_ANNOTATED_FIELD_NAME = "defaultField";
// Validators are reusable but not thread safe
protected final ConstraintValidator<A, T> validator = createValidator();
// private ConstraintValidatorContext context;
public ConstraintValidatorTestCase() {
super();
}
/**
* All constraints except {@link NotNull} should return true for a null value.
*/
public final void testIsValid_null() {
ConstraintValidatorTestCase.assertConstraintValidator(validator,
getDefaultAnnotation(), null, null, isNullValid());
}
/**
* Override this if a null value should not be valid. This is called by
* {@link #testIsValid_null()}
*/
protected boolean isNullValid() {
return true;
}
/**
* Get the annotation of type {@link #getAnnotationClass()} on the field named
* <code>defaultField</code>.
*/
protected final A getDefaultAnnotation() {
return getAnnotation(getAnnotationClass(), this.getClass(),
DEFAULT_ANNOTATED_FIELD_NAME);
}
protected abstract Class<A> getAnnotationClass();
protected A getAnnotation(Class<A> annotationClass, Class<?> objectClass,
String fieldName) {
for (Field field : objectClass.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
A annotation = field.getAnnotation(annotationClass);
if (annotation == null) {
throw new IllegalArgumentException(objectClass + "." + fieldName
+ " is not annotated with " + annotationClass);
}
return annotation;
}
}
throw new IllegalArgumentException(objectClass
+ " does not have a field called " + fieldName);
}
protected abstract ConstraintValidator<A, T> createValidator();
/**
* Assert result of validating <code>value</code> with <code>validator</code>
* initialized with the annotation of the <code>defaultField</code>.
*
* @param value the Value to validate
* @param expected the expected result of a calling <code>isValid</code>
*/
protected void assertConstraintValidator(T value, boolean expected) {
assertConstraintValidator(validator, getDefaultAnnotation(), null, value,
expected);
}
/**
* Asserts the validity of a value using the given validator, annotation, and
* context.
*
* @param <T> object type
* @param <A> the constraint annotation type
* @param validator the {@link ConstraintValidator} to test
* @param annotation the constraint annotation to initialize the validator.
* @param context The context for the validator
* @param value the value to validate.
* @param expected the expected result
*/
public static <T, A extends Annotation> void assertConstraintValidator(
ConstraintValidator<A, T> validator, A annotation,
ConstraintValidatorContext context, T value, boolean expected) {
validator.initialize(annotation);
String message = validator.getClass().getName() + "(" + annotation
+ ").isValid(" + value + ", " + context + ")";
assertEquals(message, expected, validator.isValid(value, context));
}
}