1

I am trying to write Functional test cases using Cucumber. Everything works fine until I try to Autowired any of the Spring Component and use it inside anywhere in Cucumber Test classes.

I am using the below configuration in maven pom.xml

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.version>5.1.3</cucumber.version>
    </properties>

    <dependencies>
        <!-- cucumber -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java8</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- dependency injection -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.4.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.2.7.RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

I have the below classes and when I refer the auto wired class inside the step, It is giving NullPointerException in the autowired property.

@Component
public class DataUtil { 
    public void getData() {
        System.out.println( "Extract data ..");
    }
}

public class LoadDataToStagingStep {
    @Autowired
    private DataUtil dataUtil;

    @Given("all tables are empty")
    public void all_staging_tables_are_empty() {
        System.out.println("1");
    }

    @When("data is loaded")
    public void load_data(DataTable table) {
        **dataUtil.getData();**
    }

    @Then("table should have data")
    public void data_provided() {
        System.out.println("3");
    }

}

I have tried to add Context configuration as below, but it is giving different errors and not able to resolve. Can someone help how to make it work cucumber and spring boot autowiring together ?

@SpringBootTest
@AutoConfigureMockMvc
public class CucumberContextConfiguration  {

    @Before
    public void setup_cucumber_spring_context(){
        // Dummy method so cucumber will recognize this class as glue
        // and use its context configuration.
    }
} 

The below code is the working structure to use Spring @Autowired in Cucumber Functional test.

enter image description here CucumberTestContextConfiguration.Java

package com.cucumber.test;

import org.springframework.boot.test.context.SpringBootTest;

import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;

@CucumberContextConfiguration
@SpringBootTest(classes = TestConfig.class)
public class CucumberTestContextConfiguration  {

    @Before
    public void setup_cucumber_spring_context(){
        // Dummy method so cucumber will recognize this class as glue
        // and use its context configuration.
    }
} 

CucumberFunctionalTest.Java

package com.cucumber.test;

import org.junit.runner.RunWith;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources/features",
        plugin = {"pretty", "html:target/cucumber/reports"},
        glue = {"com.cucumber.test"}
        )
public class CucumberFunctionalTest {

}

DataUtil.Java

package com.cucumber.test;

import org.springframework.stereotype.Component;

@Component
public class DataUtil {

    public void getData() {
        System.out.println( "Extract data ..");
    }

}

TestStep.Java

package com.cucumber.test;

import org.springframework.beans.factory.annotation.Autowired;

import io.cucumber.datatable.DataTable;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;

public class TestStep {

    @Autowired
    private DataUtil dataUtil;

    @Given("all tables are empty")
    public void all_tables_are_empty() {
        System.out.println("1");
    }

    @When("data provided")
    public void data_provided(DataTable table) {
        dataUtil.getData();
        System.out.println("2");
    }

    @Then("tables are populated with provided data")
    public void tables_are_populated_with_provided_data() {
        System.out.println("3");
    }
}

SpringBootCucumberApplication.Java

package com.cucumber.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@SpringBootApplication
@EnableWebMvc
public class SpringBootCucumberApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootCucumberApplication.class, args);
    }

}

test_data.feature

Feature: Test Data Load
  Scenario: Verify the Test data
    Given all tables are empty
    When data provided
    Then tables are populated with provided data

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cucumber</groupId>
    <artifactId>cucumberdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.version>5.7.0</cucumber.version>
        <spring.version>5.2.5.RELEASE</spring.version>
        <spring-boot.version>2.2.6.RELEASE</spring-boot.version>
        <junit-platform.version>1.6.2</junit-platform.version>
    </properties>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-core</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java8</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-testng</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- Spring doesn't include the right version for surefire to pickup TODO: 
            Remove once the surefire or spring is upgraded -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-commons</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
Muthu
  • 43
  • 1
  • 2
  • 10
  • 1
    Is your @Before a Cucumber or a JUnit annotation? – M.P. Korstanje May 10 '20 at 00:55
  • 1
    The important bit is that your context configuration must be on the glue path. So also check your @CucumberOptions. – M.P. Korstanje May 10 '20 at 00:56
  • 1
    Before annotation is from Cucumber and I used Spring ContextConfiguration. Thank you M.P. Korstanje for your pointers. The problem was that I couldn't add CucumberContextConfiguration in version 5.1.3 and later found that it was not supported on versions before 5.6.0. After I have updated cucumber version to 5.6.0 and added CucumberContextConfiguration and also added TestConfig, it started working for Autowired without any issues. One additional observation is that If any class is already loaded by cucumber we don't need to mark it as @Component and still can refer it using Autowired. – Muthu May 10 '20 at 17:03

0 Answers0