Search code examples
javamultithreadingspringjbehave

How to make stateful JBehave steps safe for multithreaded execution


Currently, I'm injecting a steps class into a JUnit test using Spring:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration...
class MyTest extends JUnitStories {
    @Autowired private MySteps mySteps;

    public List<CandidateSteps> candidateSteps() {
        return new InstanceStepsFactory(configuration(), mySteps).createCandidateSteps();
    }

    ...
}

I'd like to run JBehave with multiple threads, so I can't inject a singleton MySteps bean any longer.

I've read http://jira.codehaus.org/browse/JBEHAVE-492 but still can't see how to solve my problem.


Solution

  • This was asked a long time ago, but the answer is: Only hold state in ThreadLocal variables or even better wrap a ThreadLocal variable in one of your own classes. For example, take this code

    The state class

    public class State {
       private ThreadLocal<String> state;
    
       public void setState(String state) {
          this.state.set(state);
       }
    
       public String getState() {
          return this.state.get();
       }
    }
    

    And the steps

    public class Steps {
       private State state;
    
       public Steps(State state) {
          this.state = state;
       }
    
       @Given("the following happens: $string")
       public void somethingHappens(String string) {
          state.setState(string);
       }
    
       @When("who knows")
       public void whoKnows() {
          String stat = state.getState();
       }
    
       @BeforeScenario
       public void cleanup() {
          state.setState(null);
       }
    }
    

    I suggest you to have something that before the scenario clears the variable, to prevent any kind of leak between different scenarios.