package org.springmodules.validation.bean.conf.loader.xml; import java.beans.PropertyDescriptor; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import junit.framework.TestCase; import org.easymock.MockControl; import org.springframework.beans.BeanUtils; import org.springmodules.validation.bean.conf.CascadeValidation; import org.springmodules.validation.bean.conf.MutableBeanValidationConfiguration; import org.springmodules.validation.bean.conf.ValidationConfigurationException; import org.springmodules.validation.bean.conf.loader.xml.handler.ClassValidationElementHandler; import org.springmodules.validation.bean.conf.loader.xml.handler.PropertyValidationElementHandler; import org.springmodules.validation.bean.rule.PropertyValidationRule; import org.springmodules.validation.bean.rule.ValidationRule; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Tests for {@link org.springmodules.validation.bean.conf.loader.xml.DefaultXmlBeanValidationConfigurationLoader}. * * @author Uri Boness */ public class DefaultXmlBeanValidationConfigurationLoaderTests extends TestCase { private DefaultXmlBeanValidationConfigurationLoader loader; private MockControl registryControl; private ValidationRuleElementHandlerRegistry registry; private MockControl configurationControl; private MutableBeanValidationConfiguration configuration; private MockControl propertyHandlerControl; private PropertyValidationElementHandler propertyHandler; private MockControl classHandlerControl; private ClassValidationElementHandler classHandler; private MockControl ruleControl; private ValidationRule rule; protected void setUp() throws Exception { registryControl = MockControl.createControl(ValidationRuleElementHandlerRegistry.class); registry = (ValidationRuleElementHandlerRegistry)registryControl.getMock(); configurationControl = MockControl.createControl(MutableBeanValidationConfiguration.class); configuration = (MutableBeanValidationConfiguration)configurationControl.getMock(); ruleControl = MockControl.createControl(ValidationRule.class); rule = (ValidationRule)ruleControl.getMock(); propertyHandlerControl = MockControl.createControl(PropertyValidationElementHandler.class); propertyHandler = (PropertyValidationElementHandler)propertyHandlerControl.getMock(); classHandlerControl = MockControl.createControl(ClassValidationElementHandler.class); classHandler = (ClassValidationElementHandler)classHandlerControl.getMock(); loader = new DefaultXmlBeanValidationConfigurationLoader(registry); } public void testHandlePropertyDefinition_WithNoRulesAndNoCascading() throws Exception { Element propertyDefinition = element("property", new String[] { "name" }, new String[] { "name" } ); replay(); loader.handlePropertyDefinition(propertyDefinition, Object.class, configuration); verify(); } public void testHandlePropertyDefinition_WithNoRulesButWithCascading() throws Exception { Element propertyDefinition = element("property", new String[] { "name", "cascade" }, new String[] { "name", "true" } ); configuration.addCascadeValidation(new CascadeValidation("name")); replay(); loader.handlePropertyDefinition(propertyDefinition, TestBean.class, configuration); verify(); } public void testHandlePropertyDefinition_WithARuleAndCascading() throws Exception { Document document = document(); Element propertyDefinition = element(document, "property", new String[] { "name", "cascade" }, new String[] { "name", "true" } ); Element ruleDefinition = element(document, "rule"); propertyDefinition.appendChild(ruleDefinition); PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(TestBean.class, "name"); configuration.addCascadeValidation(new CascadeValidation("name")); registryControl.expectAndReturn(registry.findPropertyHandler(ruleDefinition, TestBean.class, descriptor), propertyHandler); propertyHandler.handle(ruleDefinition, "name", configuration); final PropertyValidationRule propertyRule = new PropertyValidationRule("name", rule); loader = new DefaultXmlBeanValidationConfigurationLoader(registry) { protected PropertyValidationRule createPropertyRule(String propertyName, ValidationRule rule) { return propertyRule; } }; replay(); loader.handlePropertyDefinition(propertyDefinition, TestBean.class, configuration); verify(); } public void testHandlePropertyDefinition_WithoutAppropriateHandler() throws Exception { Document document = document(); Element propertyDefinition = element(document, "property", new String[] { "name", "cascade" }, new String[] { "name", "true" } ); Element ruleDefinition = element(document, "rule"); propertyDefinition.appendChild(ruleDefinition); PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(TestBean.class, "name"); configuration.addCascadeValidation(new CascadeValidation("name")); registryControl.expectAndReturn(registry.findPropertyHandler(ruleDefinition, TestBean.class, descriptor), null); replay(); try { loader.handlePropertyDefinition(propertyDefinition, TestBean.class, configuration); fail("An ValidationConfigurationException is expected to be thrown if of the configured rules has no handler"); } catch (ValidationConfigurationException xce) { // expected } verify(); } public void testHandleGlobalDefinition_WithNoRules() throws Exception { Element globalDefinition = element("global"); replay(); loader.handleGlobalDefinition(globalDefinition, TestBean.class, configuration); verify(); } public void testHandleGlobalDefinition_WithARule() throws Exception { Document document = document(); Element globalDefinition = element(document, "global"); Element ruleDefinition = element(document, "rule"); globalDefinition.appendChild(ruleDefinition); registryControl.expectAndReturn(registry.findClassHandler(ruleDefinition, TestBean.class), classHandler); classHandler.handle(ruleDefinition, configuration); replay(); loader.handleGlobalDefinition(globalDefinition, TestBean.class, configuration); verify(); } public void testHandleGlobalDefinition_WithoutAppropriateHandler() throws Exception { Document document = document(); Element globalDefinition = element(document, "global"); Element ruleDefinition = element(document, "rule"); globalDefinition.appendChild(ruleDefinition); registryControl.expectAndReturn(registry.findClassHandler(ruleDefinition, TestBean.class), null); replay(); try { loader.handleGlobalDefinition(globalDefinition, TestBean.class, configuration); fail("An ValidationConfigurationException is expected to be thrown if no proper element handler " + "could be found for a rule definition"); } catch (ValidationConfigurationException xce) { // expected } verify(); } //=============================================== Helper Methods =================================================== protected void replay() { registryControl.replay(); configurationControl.replay(); propertyHandlerControl.replay(); classHandlerControl.replay(); ruleControl.replay(); } protected void verify() { registryControl.verify(); configurationControl.verify(); propertyHandlerControl.verify(); classHandlerControl.verify(); ruleControl.verify(); } protected Document document() throws Exception { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); return builder.newDocument(); } protected Element element(Document doc, String name) throws Exception { return doc.createElement(name); } protected Element element(String name) throws Exception { return element(name, new String[0], new String[0]); } protected Element element(String name, String[] attrNames, String[] attrValues) throws Exception { return element(document(), name, attrNames, attrValues); } protected Element element(Document doc, String name, String[] attrNames, String[] attrValues) throws Exception { if (attrNames.length != attrValues.length) { throw new IllegalArgumentException("attribute names and attribute values have different sizes"); } Element element = doc.createElement(name); for (int i=0; i<attrNames.length; i++) { element.setAttribute(attrNames[i], attrValues[i]); } return element; } //=============================================== Inner Classes =================================================== public class TestBean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }