Question

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?

Was it helpful?

Solution

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> 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top