I have the following setup in my flow XML (my-flow.xml):
<view-state id="exceptionViewState" view="general_error" model="oneObjet"/>
...
<view-state id="previousViewState" view="previous_view" model="oneObjet">
<transition on="actionConfirmed" to="endState" />
</view-state>
...
<global-transitions>
<transition on-exception="com.xxx.exception.GeneralException" to="exceptionViewState"/>
</global-transitions>
And I am trying to test this flow XML by extending AbstractXmlFlowExecutionTests
public void testMyFlow_Exception() {
setCurrentState("previousViewState");
MockExternalContext context = new MockExternalContext();
context.setEventId("com.xxx.exception.GeneralException");
resumeFlow(context);
assertCurrentStateEquals("exceptionViewState");
assertResponseWrittenEquals("general_error", context);
}
When I run this test I get the following error:
org.springframework.webflow.engine.NoMatchingTransitionException: No transition found on occurence of event 'com.xxx.exception.GeneralException' in state 'previousViewState' of flow 'my-flow' -- valid transitional criteria are array<TransitionCriteria>[actionConfirmed] -- likely programmer error, check the set of TransitionCriteria for this state
At first glance it seems that the issue caused by using MockExternalContext#setEventId()
method (which I think doesn't apply to exceptions) to try and emulate an exception being thrown. But I couldn't think of another way to do this. Any ideas on how this can be achieved?
I found a way around this by stubbing a service called in the web flow to throw the exception GeneralException. This allowed me to test the exception flow:
public class ExceptionFlowTest extends AbstractXmlFlowExecutionTests {
private MyService myService;
protected void setUp() {
myService = new MyService() {
public ObjectDTO getObject() throws GeneralException {
throw new GeneralException();
}
};
}
@Override
protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
return resourceFactory.createFileResource("WebContent/WEB-INF/flows/my-flow.xml");
}
@Override
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
builderContext.registerBean("myService", myService);
}
public void testMyFlow_Exception() {
MutableAttributeMap input = new LocalAttributeMap();
MockExternalContext context = new MockExternalContext();
startFlow(input, context);
assertCurrentStateEquals("exceptionViewState");
}
}
I didn't have to change my flow XML :
<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"
start-state="getObject">
<persistence-context />
<var name="object" class="com.xxx.model.ObjectDTO" />
<action-state id="getObject">
<evaluate expression="myService.getObject()" result="object" />
<transition to="nextView" />
</action-state>
...
<global-transitions>
<transition on-exception="com.xxx.exception.GeneralException" to="exceptionViewState"/>
</global-transitions>
</flow>