org.springmodules.validation.bean.BeanValidatorTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springmodules.validation.bean.BeanValidatorTests.java

Source

/*
 * Copyright 2004-2005 the original author or authors.
 *
 * 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 org.springmodules.validation.bean;

import java.util.*;

import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.beans.BeanWrapper;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springmodules.validation.bean.conf.BeanValidationConfiguration;
import org.springmodules.validation.bean.conf.CascadeValidation;
import org.springmodules.validation.bean.conf.loader.BeanValidationConfigurationLoader;
import org.springmodules.validation.bean.converter.ErrorCodeConverter;
import org.springmodules.validation.bean.rule.ValidationRule;
import org.springmodules.validation.util.condition.common.AlwaysFalseCondition;
import org.springmodules.validation.util.condition.common.AlwaysTrueCondition;

/**
 * Tests for {@link org.springmodules.validation.bean.BeanValidator}.
 *
 * @author Uri Boness
 */
public class BeanValidatorTests extends TestCase {

    private BeanValidator validator;

    private MockControl errorsControl;

    private Errors errors;

    private MockControl configurationControl;

    private BeanValidationConfiguration configuration;

    private MockControl ruleControl1;

    private ValidationRule rule1;

    private MockControl ruleControl2;

    private ValidationRule rule2;

    private MockControl converterControl;

    private ErrorCodeConverter converter;

    private MockControl loaderControl;

    private BeanValidationConfigurationLoader loader;

    private MockControl wrapperControl = MockControl.createControl(BeanWrapper.class);

    private BeanWrapper wrapper = (BeanWrapper) wrapperControl.getMock();

    protected void setUp() throws Exception {
        converterControl = MockControl.createControl(ErrorCodeConverter.class);
        converter = (ErrorCodeConverter) converterControl.getMock();

        loaderControl = MockControl.createControl(BeanValidationConfigurationLoader.class);
        loader = (BeanValidationConfigurationLoader) loaderControl.getMock();

        validator = new BeanValidator(loader);
        validator.setErrorCodeConverter(converter);

        errorsControl = MockControl.createControl(Errors.class);
        errors = (Errors) errorsControl.getMock();

        configurationControl = MockControl.createControl(BeanValidationConfiguration.class);
        configuration = (BeanValidationConfiguration) configurationControl.getMock();

        ruleControl1 = MockControl.createControl(ValidationRule.class);
        rule1 = (ValidationRule) ruleControl1.getMock();

        ruleControl2 = MockControl.createControl(ValidationRule.class);
        rule2 = (ValidationRule) ruleControl2.getMock();

        wrapperControl = MockControl.createControl(BeanWrapper.class);
        wrapper = (BeanWrapper) wrapperControl.getMock();
    }

    public void testSupports_WhenLoaderSupports() throws Exception {
        loaderControl.expectAndReturn(loader.supports(Object.class), true);
        replay();
        assertTrue(validator.supports(Object.class));
        verify();
    }

    public void testValidateObjectGraphConstraints_WithArrayProperty() throws Exception {
        final Object object = new Object();
        final Object[] propertyValue = new Object[0];
        final Set validatedObjects = new HashSet();

        // creating the bean with stub methods
        BeanValidator validator = new BeanValidator(loader) {
            protected void applyBeanValidation(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected BeanWrapper wrapBean(Object bean) {
                return wrapper;
            }

            protected void validateArrayProperty(Object root, Object array, String propertyName, Errors errors,
                    Set validatedObjs) {
                assertSame(object, root);
                assertSame(propertyValue, array);
                assertEquals("array", propertyName);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
            }
        };
        validator.setErrorCodeConverter(converter);

        // configuring the expectations of the bean wrapper that will be used to extract the array property
        wrapperControl.expectAndReturn(wrapper.getPropertyType("array"), Object[].class);
        wrapperControl.expectAndReturn(wrapper.getPropertyValue("array"), propertyValue);

        CascadeValidation[] cascadeValidations = new CascadeValidation[] { new CascadeValidation("array") };
        configurationControl.expectAndReturn(configuration.getCascadeValidations(), cascadeValidations);
        loaderControl.expectAndReturn(loader.loadConfiguration(Object.class), configuration);

        replay();
        validator.validateObjectGraphConstraints(object, object, errors, validatedObjects);
        assertFalse(validatedObjects.isEmpty());
        assertEquals(object, validatedObjects.iterator().next());
        verify();
    }

    public void testValidateObjectGraphConstraints_WithListProperty() throws Exception {
        final Object object = new Object();
        final List propertyValue = new ArrayList();
        final Set validatedObjects = new HashSet();

        // creating the bean with stub methods
        BeanValidator validator = new BeanValidator(loader) {
            protected void applyBeanValidation(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected BeanWrapper wrapBean(Object bean) {
                return wrapper;
            }

            protected void validateListOrSetProperty(Object root, Collection collection, String propertyName,
                    Errors errors, Set validatedObjs) {
                assertSame(object, root);
                assertSame(propertyValue, collection);
                assertEquals("list", propertyName);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
            }
        };
        validator.setErrorCodeConverter(converter);

        // configuring the expectations of the bean wrapper that will be used to extract the array property
        wrapperControl.expectAndReturn(wrapper.getPropertyType("list"), List.class);
        wrapperControl.expectAndReturn(wrapper.getPropertyValue("list"), propertyValue);

        CascadeValidation[] cascadeValidations = new CascadeValidation[] { new CascadeValidation("list") };
        configurationControl.expectAndReturn(configuration.getCascadeValidations(), cascadeValidations);
        loaderControl.expectAndReturn(loader.loadConfiguration(Object.class), configuration);

        replay();
        validator.validateObjectGraphConstraints(object, object, errors, validatedObjects);
        assertFalse(validatedObjects.isEmpty());
        assertEquals(object, validatedObjects.iterator().next());
        verify();
    }

    public void testValidateObjectGraphConstraints_WithSetProperty() throws Exception {
        final Object object = new Object();
        final Set propertyValue = new HashSet();
        final Set validatedObjects = new HashSet();

        // creating the bean with stub methods
        BeanValidator validator = new BeanValidator(loader) {
            protected void applyBeanValidation(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected BeanWrapper wrapBean(Object bean) {
                return wrapper;
            }

            protected void validateListOrSetProperty(Object root, Collection collection, String propertyName,
                    Errors errors, Set validatedObjs) {
                assertSame(object, root);
                assertSame(propertyValue, collection);
                assertEquals("set", propertyName);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
            }
        };
        validator.setErrorCodeConverter(converter);

        // configuring the expectations of the bean wrapper that will be used to extract the array property
        wrapperControl.expectAndReturn(wrapper.getPropertyType("set"), Set.class);
        wrapperControl.expectAndReturn(wrapper.getPropertyValue("set"), propertyValue);

        CascadeValidation[] cascadeValidations = new CascadeValidation[] { new CascadeValidation("set") };
        configurationControl.expectAndReturn(configuration.getCascadeValidations(), cascadeValidations);
        loaderControl.expectAndReturn(loader.loadConfiguration(Object.class), configuration);

        replay();
        validator.validateObjectGraphConstraints(object, object, errors, validatedObjects);
        assertFalse(validatedObjects.isEmpty());
        assertEquals(object, validatedObjects.iterator().next());
        verify();
    }

    public void testValidateObjectGraphConstraints_WithMapProperty() throws Exception {
        final Object object = new Object();
        final Map propertyValue = new HashMap();
        final Set validatedObjects = new HashSet();

        // creating the bean with stub methods
        BeanValidator validator = new BeanValidator(loader) {
            protected void applyBeanValidation(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected BeanWrapper wrapBean(Object bean) {
                return wrapper;
            }

            protected void validateMapProperty(Object root, Map map, String propertyName, Errors errors,
                    Set validatedObjs) {
                assertSame(object, root);
                assertSame(propertyValue, map);
                assertEquals("map", propertyName);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
            }
        };
        validator.setErrorCodeConverter(converter);

        // configuring the expectations of the bean wrapper that will be used to extract the array property
        wrapperControl.expectAndReturn(wrapper.getPropertyType("map"), Map.class);
        wrapperControl.expectAndReturn(wrapper.getPropertyValue("map"), propertyValue);

        CascadeValidation[] cascadeValidations = new CascadeValidation[] { new CascadeValidation("map") };
        configurationControl.expectAndReturn(configuration.getCascadeValidations(), cascadeValidations);
        loaderControl.expectAndReturn(loader.loadConfiguration(Object.class), configuration);

        replay();
        validator.validateObjectGraphConstraints(object, object, errors, validatedObjects);
        assertFalse(validatedObjects.isEmpty());
        assertEquals(object, validatedObjects.iterator().next());
        verify();
    }

    public void testValidateObjectGraphConstraints_WithSubBeanProperty() throws Exception {
        final Object object = new Object();
        final Object propertyValue = new Object();
        final Set validatedObjects = new HashSet();

        // creating the bean with stub methods
        BeanValidator validator = new BeanValidator(loader) {
            protected void applyBeanValidation(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected BeanWrapper wrapBean(Object bean) {
                return wrapper;
            }

            protected void validatedSubBean(Object root, Object subBean, String propertyName, Errors errors,
                    Set validatedObjs) {
                assertSame(object, root);
                assertSame(propertyValue, subBean);
                assertEquals("subBean", propertyName);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
            }
        };
        validator.setErrorCodeConverter(converter);

        // configuring the expectations of the bean wrapper that will be used to extract the array property
        wrapperControl.expectAndReturn(wrapper.getPropertyType("subBean"), Object.class);
        wrapperControl.expectAndReturn(wrapper.getPropertyValue("subBean"), propertyValue);

        CascadeValidation[] cascadeValidations = new CascadeValidation[] { new CascadeValidation("subBean") };
        configurationControl.expectAndReturn(configuration.getCascadeValidations(), cascadeValidations);
        loaderControl.expectAndReturn(loader.loadConfiguration(Object.class), configuration);

        replay();
        validator.validateObjectGraphConstraints(object, object, errors, validatedObjects);
        assertFalse(validatedObjects.isEmpty());
        assertEquals(object, validatedObjects.iterator().next());
        verify();
    }

    public void testValidateArrayProperty() throws Exception {
        final Object root = new Object();
        final Object element1 = new Object();
        final Object element2 = new Object();
        final Object[] array = new Object[] { element1, element2 };
        final Set validatedObjects = new HashSet();

        BeanValidator validator = new BeanValidator(loader) {
            private int runCount = 0;

            protected void validateObjectGraphConstraints(Object rootObject, Object obj, Errors errors,
                    Set validatedObjs) {
                assertSame(root, rootObject);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
                switch (runCount++) {
                case 0:
                    assertSame(element1, obj);
                    break;
                case 1:
                    assertSame(element2, obj);
                }
            }
        };
        validator.setErrorCodeConverter(converter);

        errors.pushNestedPath("array[0]");
        errors.popNestedPath();
        errors.pushNestedPath("array[1]");
        errors.popNestedPath();

        replay();
        validator.validateArrayProperty(root, array, "array", errors, validatedObjects);
        verify();
    }

    public void testValidateListOrSetProperty_WithList() throws Exception {
        final Object root = new Object();
        final Object element1 = new Object();
        final Object element2 = new Object();
        final List list = new ArrayList();
        list.add(element1);
        list.add(element2);
        final Set validatedObjects = new HashSet();

        BeanValidator validator = new BeanValidator(loader) {
            private int runCount = 0;

            protected void validateObjectGraphConstraints(Object rootObject, Object obj, Errors errors,
                    Set validatedObjs) {
                assertSame(root, rootObject);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
                switch (runCount++) {
                case 0:
                    assertSame(element1, obj);
                    break;
                case 1:
                    assertSame(element2, obj);
                }
            }
        };
        validator.setErrorCodeConverter(converter);

        errors.pushNestedPath("list[0]");
        errors.popNestedPath();
        errors.pushNestedPath("list[1]");
        errors.popNestedPath();

        replay();
        validator.validateListOrSetProperty(root, list, "list", errors, validatedObjects);
        verify();
    }

    public void testValidateListOrSetProperty_WithSet() throws Exception {
        final Object root = new Object();
        final Object element1 = new Integer(1);
        final Object element2 = new Integer(2);
        final Set set = new TreeSet();
        set.add(element1);
        set.add(element2);
        final Set validatedObjects = new HashSet();

        BeanValidator validator = new BeanValidator(loader) {
            private int runCount = 0;

            protected void validateObjectGraphConstraints(Object rootObject, Object obj, Errors errors,
                    Set validatedObjs) {
                assertSame(root, rootObject);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
                switch (runCount++) {
                case 0:
                    assertSame(element1, obj);
                    break;
                case 1:
                    assertSame(element2, obj);
                }
            }
        };
        validator.setErrorCodeConverter(converter);

        errors.pushNestedPath("set[0]");
        errors.popNestedPath();
        errors.pushNestedPath("set[1]");
        errors.popNestedPath();

        replay();
        validator.validateListOrSetProperty(root, set, "set", errors, validatedObjects);
        verify();
    }

    public void testValidateMapProperty() throws Exception {
        final Object root = new Object();
        final Object element1 = new Object();
        final Object element2 = new Object();
        final Map map = new HashMap();
        map.put("e1", element1);
        map.put("e2", element2);
        final Set validatedObjects = new HashSet();

        BeanValidator validator = new BeanValidator(loader) {
            protected void validateObjectGraphConstraints(Object rootObject, Object obj, Errors errors,
                    Set validatedObjs) {
                assertSame(root, rootObject);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
                assertTrue(element1 == obj || element2 == obj);
            }
        };
        validator.setErrorCodeConverter(converter);

        errors.pushNestedPath("map[e1]");
        errors.popNestedPath();
        errors.pushNestedPath("map[e2]");
        errors.popNestedPath();

        replay();
        validator.validateMapProperty(root, map, "map", errors, validatedObjects);
        verify();
    }

    public void testValidatedSubBean() throws Exception {
        final Object root = new Object();
        final Object subBean = new Object();
        final Set validatedObjects = new HashSet();

        BeanValidator validator = new BeanValidator(loader) {
            protected void validateObjectGraphConstraints(Object rootObject, Object obj, Errors errors,
                    Set validatedObjs) {
                assertSame(root, rootObject);
                assertSame(BeanValidatorTests.this.errors, errors);
                assertSame(validatedObjects, validatedObjs);
                assertSame(subBean, obj);
            }
        };
        validator.setErrorCodeConverter(converter);

        errors.pushNestedPath("bean");
        errors.popNestedPath();

        replay();
        validator.validatedSubBean(root, subBean, "bean", errors, validatedObjects);
        verify();
    }

    public void testApplyBeanValidation() throws Exception {
        final Object object = new Object();

        BeanValidator validator = new BeanValidator(loader) {
            protected void applyGlobalValidationRules(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected void applyPropertiesValidationRules(BeanValidationConfiguration conf, Object obj,
                    Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }

            protected void applyCustomValidator(BeanValidationConfiguration conf, Object obj, Errors errors) {
                assertSame(configuration, conf);
                assertSame(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }
        };

        replay();
        validator.applyBeanValidation(configuration, object, errors);
        verify();
    }

    public void testApplyGlobalValidationRules() throws Exception {
        Object object = new Object();

        Object[] args = new Object[0];
        ruleControl1.expectAndReturn(rule1.isApplicable(object), true);
        ruleControl1.expectAndReturn(rule1.getCondition(), new AlwaysFalseCondition());
        ruleControl1.expectAndReturn(rule1.getErrorCode(), "errorCode1");
        ruleControl1.expectAndReturn(rule1.getDefaultErrorMessage(), "message1");
        ruleControl1.expectAndReturn(rule1.getErrorArguments(object), args);

        ruleControl2.expectAndReturn(rule2.isApplicable(object), true);
        ruleControl2.expectAndReturn(rule2.getCondition(), new AlwaysTrueCondition());

        ValidationRule[] globalRules = new ValidationRule[] { rule1, rule2 };
        configurationControl.expectAndReturn(configuration.getGlobalRules(), globalRules);

        converterControl.expectAndReturn(converter.convertGlobalErrorCode("errorCode1", Object.class),
                "_errorCode1");

        errorsControl.expectAndReturn(errors.getNestedPath(), "");
        errors.reject("_errorCode1", args, "message1");

        replay();
        validator.applyGlobalValidationRules(configuration, object, errors);
        verify();
    }

    public void testApplyPropertiesValidationRules() throws Exception {
        final Object object = new Object();

        final ValidationRule[] rules = new ValidationRule[] { rule1, rule2 };
        configurationControl.expectAndReturn(configuration.getValidatedProperties(), new String[] { "name" });
        configurationControl.expectAndReturn(configuration.getPropertyRules("name"), rules);

        BeanValidator validator = new BeanValidator() {
            protected void validateAndShortCircuitRules(ValidationRule[] validationRules, String propertyName,
                    Object obj, Errors errors) {
                assertSame(rules, rules);
                assertEquals("name", propertyName);
                assertEquals(object, obj);
                assertSame(BeanValidatorTests.this.errors, errors);
            }
        };
        validator.setErrorCodeConverter(converter);

        replay();
        validator.applyPropertiesValidationRules(configuration, object, errors);
        verify();
    }

    public void testValidateAndShortCircuitRules_WhenOnlyTheSecondFails() throws Exception {
        Object object = new Object();

        ruleControl1.expectAndReturn(rule1.isApplicable(object), true);
        ruleControl1.expectAndReturn(rule1.getCondition(), new AlwaysTrueCondition());

        Object[] args = new Object[0];
        ruleControl2.expectAndReturn(rule2.isApplicable(object), true);
        ruleControl2.expectAndReturn(rule2.getCondition(), new AlwaysFalseCondition());
        ruleControl2.expectAndReturn(rule2.getErrorCode(), "errorCode2");
        ruleControl2.expectAndReturn(rule2.getDefaultErrorMessage(), "message2");
        ruleControl2.expectAndReturn(rule2.getErrorArguments(object), args);

        ValidationRule[] rules = new ValidationRule[] { rule1, rule2 };

        converterControl.expectAndReturn(converter.convertPropertyErrorCode("errorCode2", Object.class, "name"),
                "_errorCode2");

        errors.rejectValue("name", "_errorCode2", args, "message2");

        replay();
        validator.validateAndShortCircuitRules(rules, "name", object, errors);
        verify();
    }

    public void testValidateAndShortCircuitRules_WhenTheFirstFails() throws Exception {
        Object object = new Object();

        Object[] args = new Object[0];
        ruleControl1.expectAndReturn(rule1.isApplicable(object), true);
        ruleControl1.expectAndReturn(rule1.getCondition(), new AlwaysFalseCondition());
        ruleControl1.expectAndReturn(rule1.getErrorCode(), "errorCode1");
        ruleControl1.expectAndReturn(rule1.getDefaultErrorMessage(), "message1");
        ruleControl1.expectAndReturn(rule1.getErrorArguments(object), args);

        ValidationRule[] rules = new ValidationRule[] { rule1, rule2 };

        converterControl.expectAndReturn(converter.convertPropertyErrorCode("errorCode1", Object.class, "name"),
                "_errorCode1");

        errors.rejectValue("name", "_errorCode1", args, "message1");

        replay();
        validator.validateAndShortCircuitRules(rules, "name", object, errors);
        verify();
    }

    public void testValidateAndShortCircuitRules_WhenNoneFail() throws Exception {
        Object object = new Object();

        ruleControl1.expectAndReturn(rule1.isApplicable(object), true);
        ruleControl1.expectAndReturn(rule1.getCondition(), new AlwaysTrueCondition());

        ruleControl2.expectAndReturn(rule2.isApplicable(object), true);
        ruleControl2.expectAndReturn(rule2.getCondition(), new AlwaysTrueCondition());

        ValidationRule[] rules = new ValidationRule[] { rule1, rule2 };

        replay();
        validator.validateAndShortCircuitRules(rules, "name", object, errors);
        verify();
    }

    public void testApplyCustomValidator() throws Exception {
        Object object = new Object();

        MockControl customValidatorControl = MockControl.createControl(Validator.class);
        Validator customValidator = (Validator) customValidatorControl.getMock();
        customValidator.validate(object, errors);
        configurationControl.expectAndReturn(configuration.getCustomValidator(), customValidator);

        replay();
        validator.applyCustomValidator(configuration, object, errors);
        verify();
    }

    public void testApplyCustomValidator_WhenThereIsNoCustomValidator() throws Exception {
        Object object = new Object();

        configurationControl.expectAndReturn(configuration.getCustomValidator(), null);

        replay();
        validator.applyCustomValidator(configuration, object, errors);
        verify();
    }

    //=============================================== Helper Methods ===================================================

    protected void replay() {
        ruleControl1.replay();
        ruleControl2.replay();
        configurationControl.replay();
        errorsControl.replay();
        converterControl.replay();
        loaderControl.replay();
        wrapperControl.replay();
    }

    protected void verify() {
        ruleControl1.verify();
        ruleControl2.verify();
        configurationControl.verify();
        errorsControl.verify();
        converterControl.verify();
        loaderControl.verify();
        wrapperControl.verify();
    }

}