maddy
maddy

Reputation: 23

Autowiring a field in a Cucumber step produces NullPointerException

Cucumber runner configuration :

@RunWith(Cucumber.class)
@CucumberOptions(features = "/features",glue {""})
@ContextConfiguration(classes = Init.class,
        initializers = ConfigFileApplicationContextInitializer.class)
public class Test {
}

Feature file :

class feature {
  Scenario: Save test in db.
    When I inject a payload in the aws queue
    Then it should be integrated in database
}

Step Definition file::

@CucumberAbstract
@ContextConfiguration("classpath:application.yml")
public class MyStepdefs {

    @Autowired
    private QueueMessagingTemplate queueMessagingTemplate;

    @Autowired
    TestRepository testRepository;

    String message = "Hi";

    public MyStepdefs() {
        When("^I inject a payload in the aws queue$", () -> {
            this.queueMessagingTemplate.convertAndSend("QUEUE_NAME", message);
        });
    }

    @Then("^it should be integrated in database$")
    public void itShouldBeIntegratedInDatabase() throws Throwable {
        //validations
    }
}

I tried creating a custom annotation here and using this annotation on top of stepDefinition file. AbstractTest :::

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration(classes = Init.class, loader = 
                      SpringApplicationContextLoader.class)
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public @interface CucumberAbstract {
}

Upvotes: 1

Views: 4799

Answers (2)

alexcornejo
alexcornejo

Reputation: 163

Actually what you need is to integrate Cucumber with Spring Boot. So you need to add these dependencies for you maven project:

    <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>4.7.4</version>
        </dependency>

        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>4.7.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>4.7.4</version>
        </dependency>

Your cucumber runner is the same:

@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"}, features = {"src/main/resources"})
public class ReportCaseCucumberTest {
}

Now in you StepDefinition class you need to configure the ContextConfiguration to be able to use Spring.

@SpringBootTest
@ContextConfiguration(
        classes = Application.class,
        loader = SpringBootContextLoader.class)
public class StepsDefinitions {

    @Autowired
    private ApplicationContext appContext;
}

Now in you StepDefinition class you can use "Autowired" annotation to inject beans.

This solved my problem, also you can check this tutorial: https://medium.com/@bcarunmail/set-up-and-run-cucumber-tests-in-spring-boot-application-d0c149d26220

Upvotes: 1

davidxxx
davidxxx

Reputation: 131346

The Cucumber runner (cucumber.api.junit.Cucumber) doesn't load any Spring context.
So your cucumber step class is not Spring aware.
To inject a bean into a field of your class, you have to load the Spring context, in your case the Spring Boot context.

So specifying @SpringBootTest is what you are looking for :

@SpringBootTest
public class MyStepdefs {
  ...
}

Upvotes: 3

Related Questions