Introduction
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
parent="parent">
<view-state id="startPage" view="main/startPage.jsp">
<transition on="next" to="generateError"/>
</view-state>
<action-state id="generateError">
<evaluate expression="checkParameterController"/>
<transition on="ok" to="OkView"/>
<transition on="ko" to="KoView"/>
</action-state>
<end-state id="OkView"
view="main/finalOkView.jsp"/>
<end-state id="KoView"
view="main/finalKoView.jsp"/></flow>
And the parent flow (parent.xml):
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
abstract="true">
<end-state id="errorState"
view="commonErrorPage.jsp"/>
<global-transitions>
<transition on-exception="java.lang.Exception"
to="errorState"/></global-transitions>
</flow>
When executing tests, Spring provides us with a quite useful class: AbstractXmlFlowExecutionTests, in the org.springframework.webflow.test.execution package. This class has a variety of methods that will help us test the flow. The most interesting:
FlowDefinitionResource
getResource(FlowDefinitionResourceFactory resourceFactory)
FlowDefinitionResource[] getModelResources(FlowDefinitionResourceFactory
resourceFactory)
void configureFlowBuilderContext(MockFlowBuilderContext builderContext)
Lets us customize the builder context. I use it for registering the beans that will use in the test as this is the way it's indicated at the class javadoc.
void registerMockFlowBeans(ConfigurableBeanFactory flowBeanFactory)
Allows registering the beans that will be used by the flow to be tested. For example:
flowBeanFactory.registerSingleton("myService", new MyMockService());
Testing the flow
I've divided it in two classes in order to separate configuration from tests cases:public class BaseTestFlow extends AbstractXmlFlowExecutionTests {
protected ApplicationContext applicationContext;
/**
* This method returns
the flow to be tested.*/
protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
return resourceFactory.createFileResource("src/test/resources/flows/main.xml");
}
/**
* Needs to be overridden
if the flow to be tested inherits from another flow. In this case, we register
its parent flow.*/
protected FlowDefinitionResource[]
getModelResources(FlowDefinitionResourceFactory resourceFactory) {
FlowDefinitionResource[] flowDefinitionResources = new FlowDefinitionResource[1];
flowDefinitionResources[0] = resourceFactory.createFileResource("src/test/resources/flows/parent.xml");
return flowDefinitionResources;
}
/**
* Registers beans used
by the tested flow.*/
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
applicationContext = new ClassPathXmlApplicationContext(new String[] {
"classpath:xpadro/spring/test/configuration/root-context.xml",
"classpath:xpadro/spring/test/configuration/app-context.xml"
});
builderContext.registerBean("checkParameterController", applicationContext.getBean("checkParameterController"));
}
/*
protected void registerMockFlowBeans(ConfigurableBeanFactory
flowBeanFactory) {flowBeanFactory.registerSingleton("checkParameterController", new CheckParameterController());
}
*/
}
You could simply delete configureFlowBuilderContext method and use registerMockFlowBeans method instead if you don't want/need to start your own test context.
public class TestFlow extends BaseTestFlow {
public void
testFlowStarts() {MockExternalContext externalContext = new MockExternalContext();
startFlow(externalContext);
assertFlowExecutionActive();
assertCurrentStateEquals("startPage");
}
public void
testNavigation() {
MockExternalContext
externalContext = new MockExternalContext();setCurrentState("startPage");
externalContext.setEventId("next");
externalContext.getMockRequestParameterMap().put("inputField", "yes");
getFlowScope().put("testFlowVar", "testValue");
resumeFlow(externalContext);
assertCurrentStateEquals("OkView");
assertEquals("testValue", getFlowScope().get("testFlowVar"));
}
public void
testGlobalTransition() {
MockExternalContext
externalContext = new MockExternalContext();setCurrentState("startPage");
externalContext.setEventId("next");
externalContext.getMockRequestParameterMap().put("inputField", "error");
resumeFlow(externalContext);
assertFlowExecutionOutcomeEquals("errorState");
}
}
No comments:
Post a Comment