Tag Archives: JBehave

Scoping JBehave tests with Spring

Rule number 1 while running Jbehave tests (or any integration test really) is to execute the test scenarios independently from each other. Meaning the application state must be reset before each and every scenario run.

The code below presents a generic way to accomplish this reset while using JBehave and Spring. This approach is articulated around 2 components:

1) ScenarioContext

A class responsible for creating and cleaning up the data used by the test scenarios. This usually encompasses all kind of static and reference data plus any messages being enqueued/dequeued at the boundaries of the application (in this particular example the messages being enqueued are trade messages).

public class ScenarioContext {

    private List trades=new ArrayList();

    public void addTrade(Trade trade){
        trades.add(trade);
    }

    public ScenarioContext(){
        trades = new ArrayList();
    }
    @PostConstruct
    public void resetTrades(){
        trades.clear();
    }

    public Trade getFirstTrade(){
        return trades.get(0);
    }
}

2) ScenarioScope

This class is responsible for cleaning up the scenario context whenever a new test scenario is being run. It is defined as a custom scope Spring bean which creates a new instance of the object(s) under scope whenever JBehave is about to run a new scenario (the @BeforeScenario below is a JBehave annotation which allows the annotated method to run before a scenario).

public class ScenarioScope implements Scope {

    private final ConcurrentMap<String, Object> cache = new ConcurrentHashMap();

    @BeforeScenario
    public void startScenario(){
        cache.clear();
    }

    @Override
    public Object get(String name, ObjectFactory objectFactory) throws IllegalStateException{
        if (!cache.containsKey(name)){
           cache.putIfAbsent(name, objectFactory.getObject());
        }
        return cache.get(name);

    }
    ....

The ScenarioContext lifecycle is tied to the ScenarioScope in the Spring config file:


 <bean id="scenarioScope" class="foo.bar.ScenarioScope"/>

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="scenario" value-ref="scenarioScope"/>
            </map>
        </property>
    </bean>

    <bean id="scenarioContext" class="foo.bar.ScenarioContext" scope="scenario">
        <aop:scoped-proxy/>
    </bean>

Full code can be found here.

Advertisements