Integration Testing of Springboot with Cucumber

HOME

In this tutorial, I am going to build an automation framework to test Springboot application with Cucumber and Rest Assured.

What is Springboot?

Spring Boot is an open-source micro framework maintained by a company called Pivotal. It provides Java developers with a platform to get started with an auto configurable production-grade Spring application. With it, developers can get started quickly without losing time on preparing and configuring their Spring application.

What is Cucumber?

Cucumber is a software tool that supports behavior-driven development (BDD). Cucumber can be defined as a testing framework, driven by plain English. It serves as documentation, automated tests, and a development aid – all in one.

This framework consists of:

  1. Springboot – 2.5.2
  2. Cucumber – 6.10.4
  3. Java 11
  4. JUnit – 4.12
  5. Maven – 3.8.1
  6. RestAssured – 4.3.3

Steps to setup Cucumber Test Automation Framework for API Testing using Rest-Assured

  1. Add SpringbootTest, Rest-Assured and Cucumber dependencies to the project
  2. Create a directory src/test/resources and create a feature file under src/test/resources
  3. Create the Step Definition class or Glue Code for the Test Scenario
  4. Create a Cucumber Runner class
  5. Run the tests from JUnit
  6. Run the tests from Command Line
  7. Cucumber Report Generation

Below is the structure of a SpringBoot  application project

Below are various Java classes present in a SpringBoot REST Application.

  • SpringBootRestServiceApplication.java – The Spring Boot Application class generated with Spring Initializer. This class acts as the launching point for application.
  • pom.xml – Contains all the dependencies needed to build this project. 
  • Student.java – This is JPA Entity for Student class
  • StudentRepository.java – This is JPA Repository for Student. This is created using Spring Data JpaRepository.
  • StudentController.java – Spring Rest Controller exposing all services on the student resource.
  • CustomizedExceptionHandler.java – This implements global exception handling and customize the responses based on the exception type.
  • ErrorDetails.java – Response Bean to use when exceptions are thrown from API.
  • StudentNotFoundException.java – Exception thrown from resources when student is not found.
  • data.sql –  Data is loaded from data.sql into Student table. Spring Boot would execute this script after the tables are created from the entities.
  • application.properties – Spring Boot automatically loads the application.properties whenever it starts up. You can de reference values from the property file in the java code through the environment.

Test Automation Framework Implementation

Step 1 – Add SpringbootTest, Rest-Assured and Cucumber dependencies to the project

To Test a SpringBoot Application , we are using Cucumber with Rest Assured. Below mentioned dependencies are added in POM.xml

       <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.3.3</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>6.10.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>6.10.4</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-spring -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>6.10.4</version>
            <scope>test</scope>
        </dependency>

Step 2 – Create a directory src/test/resources and create a feature file under src/test/resources

By default, Maven project has src/test/java directory only. Create a new directory under src/test with name of resources. Create a folder name as featured within src/test/resources directory.

Create a feature file to test Springboot application. Below is a sample feature file.

Feature: Verify springboot application using Cucumber

@ReceiveUserDetails
Scenario Outline: Send a valid Request to get user details
Given I send a request to the URL "/students" to get user details
Then the response will return status 200 and id <studentID> and names "<studentNames>" and passport_no "<studentPassportNo>"

Examples:
|studentID    |studentNames  |studentPassportNo|
|10001        |Annie         |E1234567         |
|10002        |John          |A1234568         |
|10003        |David         |C1232268         |

Step 3 – Create the Step Definition class or Glue Code for the Test Scenario

@CucumberContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringbootCucumberTestDefinitions {

    private final static String BASE_URI = "http://localhost";

    @LocalServerPort
    private int port;

    private ValidatableResponse validatableResponse;

    private void configureRestAssured() {
        RestAssured.baseURI = BASE_URI;
        RestAssured.port = port;
    }


      protected RequestSpecification requestSpecification() {
         configureRestAssured();
          return given();
     }


    @Given("I send a request to the URL {string} to get user details")
    public void iSendARequest(String endpoint) throws Throwable {
        validatableResponse = requestSpecification().contentType(ContentType.JSON)
                .when().get(endpoint).then();
        System.out.println("RESPONSE :"+validatableResponse.extract().asString());
    }

    @Then("the response will return status {int} and id {int} and names {string} and passport_no {string}")
    public void extractResponse(int status, int id, String studentName,String passportNo) {
        validatableResponse.assertThat().statusCode(equalTo(status)).body("id",hasItem(id)).body(containsString(studentName)).body(containsString(passportNo));

    }
}

The @CucumberContextConfiguration annotation tells Cucumber to use this class as the test context configuration for Spring. It is imported from:-

import io.cucumber.spring.CucumberContextConfiguration;

With the @SpringBootTest annotation, Spring Boot provides a convenient way to start up an application context to be use in a test.  It is imported from package:-

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

By default, @SpringBootTest does not start the webEnvironment to refine further  how your tests run. It has several options: MOCK(default), RANDOM_PORT, DEFINED_PORT, NONE.

RANDOM_PORT loads a WebServerApplicationContext and provides a real web environment. The embedded server is start and listen on a random port. LocalServerPort is imported from package:-

import org.springframework.boot.web.server.LocalServerPort;

The assertions are imported from Hamcrest package:-

import static org.hamcrest.Matchers.*;

Step 4 – Create a Cucumber Runner class

A runner will help us to run the feature file and acts as an interlink between the feature file and StepDefinition Class. To know more about Runner, refer this link.

package com.example.demo.runner;

import org.junit.runner.RunWith;

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

@RunWith(Cucumber.class)

@CucumberOptions(plugin = "pretty", features = {"src/test/resources/features"}, glue = {
        "com.example.demo"})

public class CucumberRunnerTests {
}

The @CucumberOptions annotation is responsible for pointing to the right feature package, configuring the plugin for a better reporting of tests in the console output, and specifying the package where extraGlue classes may be found. We use it to load configuration and classes that are shared between tests.

Step 5 – Run the tests from JUnit

You can execute the test script by right-clicking on TestRunner class -> Run As JUnit.

SpringBootTest creates an application context containing all the objects we need for the Integration Testing It, starts the embedded server, creates a web environment and then enables methods to do Integration testing.

SteStep 6 – Run the tests from Command Line

To run the tests from command line, we need to add junit-vintage-engine dependency. Starting with Spring Boot 2.4, JUnit 5’s vintage engine has been removed from spring-boot-starter-test. If we still want to write tests using JUnit 4, we need to add the following Maven dependency:

        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <scope>test</scope>
        </dependency>

Use the below command to run the tests:-

mvn test

Step 7 – Cucumber Report Generation

To get Cucumber Test Reports, add cucumber.properties under src/test/resources and add the below instruction in the file. To know more about Cucumber Report Service, refer this tutorial.

cucumber.publish.enabled=true

Below is the image of the report generated post the completion of the execution. This report can be saved in GitHub for future use.

That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s