/* * 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)); } }