How to pass variables between cucumber-jvm steps

In order to share commonalities between steps you need to use a World. In Java it is not as clear as in Ruby.

Quoting the creator of Cucumber.

The purpose of a "World" is twofold:

  1. Isolate state between scenarios.

  2. Share data between step definitions and hooks within a scenario.

How this is implemented is language specific. For example, in ruby, the implicit self variable inside a step definition points to the current scenario's World object. This is by default an instance of Object, but it can be anything you want if you use the World hook.

In Java, you have many (possibly connected) World objects.

The equivalent of the World in Cucumber-Java is all of the objects with hook or stepdef annotations. In other words, any class with methods annotated with @Before, @After, @Given and so on will be instantiated exactly once for each scenario.

This achieves the first goal. To achieve the second goal you have two approaches:

a) Use a single class for all of your step definitions and hooks

b) Use several classes divided by responsibility [1] and use dependency injection [2] to connect them to each other.

Option a) quickly breaks down because your step definition code becomes a mess. That's why people tend to use b).

[1] https://cucumber.io/docs/gherkin/step-organization/

[2] PicoContainer, Spring, Guice, Weld, OpenEJB, Needle

The available Dependency Injection modules are:

  • cucumber-picocontainer
  • cucumber-guice
  • cucumber-openejb
  • cucumber-spring
  • cucumber-weld
  • cucumber-needle

Original post here https://groups.google.com/forum/#!topic/cukes/8ugcVreXP0Y.

Hope this helps.


It's fine to share data between steps defined within a class using an instance variable. If you need to share data between steps in different classes you should look at the DI integrations (PicoContainer is the simplest).

In the example you show, I'd ask whether showing "TEST" in the scenario is necessary at all. The fact that the user is called TEST is an incidental detail and makes the scenario less readable. Why not generate a random name (or hard code something) in Create_user_with_name()?


In Pure java, I just use a Singleton object that gets created once and cleared after tests.

public class TestData_Singleton {
    private static TestData_Singleton myself = new TestData_Singleton();

    private TestData_Singleton(){ }

    public static TestData_Singleton getInstance(){
        if(myself == null){
            myself = new TestData_Singleton();
        }

        return myself;
    }

    public void ClearTestData(){
        myself = new TestData_Singleton();
    }