/* * Copyright 2004-2012 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.springframework.webflow.test.execution; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.webflow.config.FlowDefinitionResource; import org.springframework.webflow.config.FlowDefinitionResourceFactory; import org.springframework.webflow.engine.builder.FlowBuilder; import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder; import org.springframework.webflow.engine.model.builder.DefaultFlowModelHolder; import org.springframework.webflow.engine.model.builder.FlowModelBuilder; import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder; import org.springframework.webflow.engine.model.registry.FlowModelHolder; import org.springframework.webflow.engine.model.registry.FlowModelRegistry; import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl; /** * Base class for flow integration tests that verify an XML flow definition executes as expected. * <p> * Example usage: * * <pre> * public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests { * * protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) { * return resourceFactory.createClassPathResource("search-flow.xml", getClass()); * } * * public void testStartFlow() { * ExternalContext context = new MockExternalContext(); * startFlow(context); * assertCurrentStateEquals("enterSearchCriteria"); * } * * protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) { * builderContext.registerBean("searchService", new TestSearchService()); * } * * } * </pre> * * @author Keith Donald * @author Erwin Vervaet * @author Scott Andrews */ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalizedFlowExecutionTests { private FlowModelRegistry flowModelRegistry = new FlowModelRegistryImpl(); /** * Constructs a default XML flow execution test. * @see #setName(String) */ public AbstractXmlFlowExecutionTests() { super(); } /** * Constructs an XML flow execution test with given name. * @param name the name of the test */ public AbstractXmlFlowExecutionTests(String name) { super(name); } protected final FlowBuilder createFlowBuilder(FlowDefinitionResource resource) { registerDependentFlowModels(); FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(resource.getPath(), flowModelRegistry); FlowModelHolder modelHolder = new DefaultFlowModelHolder(modelBuilder); flowModelRegistry.registerFlowModel(resource.getId(), modelHolder); return new FlowModelFlowBuilder(modelHolder) { protected void registerFlowBeans(ConfigurableBeanFactory flowBeanFactory) { registerMockFlowBeans(flowBeanFactory); } }; } /** * Template method subclasses may override to return pointers to "flow model resources" needed to build the * definition of the flow being tested. Typically overridden when the flow being tested extends from another flow. * Default returns null, assuming no inheritance. * @param resourceFactory the resource factory * @return the flow definition model resources */ protected FlowDefinitionResource[] getModelResources(FlowDefinitionResourceFactory resourceFactory) { return null; } /** * Template method subclasses may override to register mock implementations of services used locally by the flow * being tested. By default, this method does nothing. * @param flowBeanFactory the local flow bean factory, you may register mock services with it using * {@link ConfigurableBeanFactory#registerSingleton(String, Object)} */ protected void registerMockFlowBeans(ConfigurableBeanFactory flowBeanFactory) { } // internal helpers private void registerDependentFlowModels() { FlowDefinitionResource[] modelResources = getModelResources(getResourceFactory()); if (modelResources != null) { for (FlowDefinitionResource modelResource : modelResources) { FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(modelResource.getPath(), flowModelRegistry); flowModelRegistry.registerFlowModel(modelResource.getId(), new DefaultFlowModelHolder(modelBuilder)); } } } }