DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Automating Cucumber Data Table to Java Object Mapping in Your Cucumber Tests
  • Integrate Cucumber in Playwright With Java
  • Keep Your Application Secrets Secret
  • Testcontainers With Kotlin and Spring Data R2DBC

Trending

  • Start Coding With Google Cloud Workstations
  • MCP Servers: The Technical Debt That Is Coming
  • System Coexistence: Bridging Legacy and Modern Architecture
  • Optimizing Integration Workflows With Spark Structured Streaming and Cloud Services
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Cucumber and Spring Boot Integration: Passing Arguments To Step Definitions Explained

Cucumber and Spring Boot Integration: Passing Arguments To Step Definitions Explained

Cucumber is a tool that supports Behavior-Driven Development (BDD). Learn how to pass arguments to step definitions when using Cucumber and Spring Boot.

By 
Gunter Rotsaert user avatar
Gunter Rotsaert
DZone Core CORE ·
Jun. 18, 24 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
5.9K Views

Join the DZone community and get the full member experience.

Join For Free

Cucumber is a tool that supports Behavior-Driven Development (BDD). In this blog, you will learn how to pass arguments to step definitions when using Cucumber and Spring Boot. Enjoy!

Introduction

In a previous post, Cucumber was introduced as a tool that supports Behavior-Driven Development (BDD). Some of the features were explained, but not how to pass arguments to step definitions. In this blog, you will learn how you can do so. The application under test is a Spring Boot application. You will also learn how you can integrate the Cucumber tests with Spring.

The sources used in this blog are available on GitHub.

Do check out the following references for extra information:

  • Cucumber Expressions
  • Cucumber Configuration: Type Registry

Prerequisites

The prerequisites for this blog are:

  • Basis Java knowledge - Java 21 is used
  • Basic Maven knowledge
  • Basic Spring Boot knowledge
  • Basic comprehension of BDD
  • Basic knowledge of Cucumber (see the previous blog for an introduction)

Application Under Test

The application under test is a basic Spring Boot application. It consists of a Controller and a Service. The Controller serves a customer endpoint that implements an OpenAPI specification. The Service is a basic implementation, storing customers in a HashMap. A customer only has a first name and a last name, just to keep things simple. The API offers the following functionality:

  • Creating a customer
  • Retrieving the customer based on the customer ID
  • Retrieving all customers
  • Deleting all customers

Spring Integration

In order to enable the Spring integration, you add the following dependency to the pom:

XML
 
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-spring</artifactId>
  <version>7.14.0</version>
  <scope>test</scope>
</dependency>


The Spring Boot application must be in a running state; therefore, you need to run the Cucumber tests with the @SpringBootTest annotation. This will start the application and you will be able to run Cucumber tests for it. In order to do so, you create a class CucumberSpringConfiguration. Add the @CucumberContextConfiguration annotation so that the Spring integration is enabled. The Spring Boot application starts on a random port; therefore, you store the port in a system property so that you will be able to use it when you need to call the API.

Java
 
@CucumberContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CucumberSpringConfiguration {
    @LocalServerPort
    private int port;
 
    @PostConstruct
    public void setup() {
        System.setProperty("port", String.valueOf(port));
    }
}


The Cucumber step definitions will extend this class.

Tests can be run via Maven:

Shell
 
$ mvn clean verify


Test: Add Customer Using Arguments

The Add Customer test will add a customer to the customer list and will verify that the customer is added to the list. The feature file is the following. Do note that the first name (John) and last name (Doe) are within quotes. This way, Cucumber is able to recognize a string argument.

Plain Text
 
Scenario: Add customer
    Given an empty customer list
    When customer 'John' 'Doe' is added
    Then the customer 'John' 'Doe' is added to the customer list


The corresponding step definitions are the following.

  • When: The first name and last name placeholders are represented with {string} and they are mapped as arguments to the method. This way, the arguments are accessible to the step definition.
  • Then: In a similar way, the arguments are passed to the step definition.
Java
 
public class StepDefinitions extends CucumberSpringConfiguration {
 
    final int port = Integer.parseInt(System.getProperty("port"));
    final RestClient restClient = RestClient.create();
 
    @Given("an empty customer list")
    public void an_empty_customer_list() {
        ResponseEntity<Void> response = restClient.delete()
                .uri("http://localhost:"+ port + "/customer")
                .retrieve()
                .toBodilessEntity();
    }
 
    @When("customer {string} {string} is added")
    public void customer_firstname_lastname_is_added(String firstName, String lastName) {
        Customer customer = new Customer(firstName, lastName);
        ResponseEntity<Void> response = restClient.post()
                .uri("http://localhost:"+ port + "/customer")
                .contentType(APPLICATION_JSON)
                .body(customer)
                .retrieve()
                .toBodilessEntity();
        assertThat(response.getStatusCode().is2xxSuccessful()).isTrue();
    }
 
    @Then("the customer {string} {string} is added to the customer list")
    public void the_customer_first_name_last_name_is_added_to_the_customer_list(String firstName, String lastName) {
        List<Customer> customers = restClient.get()
                .uri("http://localhost:"+ port + "/customer")
                .retrieve()
                .body(new ParameterizedTypeReference<>() {});
        assertThat(customers).contains(new Customer(firstName, lastName));
    }
    ...
}


Note that the arguments are used to create a Customer object which is defined in the step definitions class. This class contains the fields, getters, setters, equals, and hashCode implementations.

Java
 
public static class Customer {
        private String firstName;
        private String lastName;
        ...
}


Test: Add Customers Using Arguments

When you want to add several customers, you can chain the same step definition by means of an And using different arguments. The feature file is the following, the step definitions remain the same.

Plain Text
 
Scenario: Add customers
    Given an empty customer list
    When customer 'John' 'Doe' is added
    And customer 'David' 'Beckham' is added
    Then the customer 'John' 'Doe' is added to the customer list
    And the customer 'David' 'Beckham' is added to the customer list


Test: Add Customer Using DataTable

The previous tests all started with an empty customer list. The next test will add some data to the customer list as a starting point. You can, of course, use the step definition customer firstName lastName is added and invoke it multiple times, but you can also use a DataTable. The DataTable must be the last argument in a step definition. The feature file is the following and the DataTable is used in the Given-clause.

Plain Text
 
Scenario: Add customer to existing customers
    Given the following customers:
      | John  | Doe     |
      | David | Beckham |
    When customer 'Bruce' 'Springsteen' is added
    Then the customer 'Bruce' 'Springsteen' is added to the customer list


In the implementation of the step definition, you now see that the arguments are passed as a DataTable. It is a table containing strings, so you need to parse the table yourself.

Java
 
@Given("the following customers:")
public void the_following_customers(io.cucumber.datatable.DataTable dataTable) {
 
    for (List<String> customer : dataTable.asLists()) {
        customer_firstname_lastname_is_added(customer.get(0), customer.get(1));
    }
}


Test: Add Customer Using Parameter Type

In the previous test, you needed to parse the DataTable yourself. Wouldn’t it be great if the DataTable could be mapped immediately to a Customer object? This is possible if you define a parameter type for it. You create a parameter type customerEntry and annotate it with @DataTableType. You use the string arguments of a DataTable to create a Customer object. You do so in a class ParameterTypes, which is considered as best practice.

Java
 
public class ParameterTypes {
    @DataTableType
    public StepDefinitions.Customer customerEntry(Map<String, String> entry) {
        return new StepDefinitions.Customer(
                entry.get("firstName"),
                entry.get("lastName"));
    }
}


The feature file is identical to the previous one, only the step definition has changed in order to have a unique step definition.

Plain Text
 
Scenario: Add customer to existing customers with parameter type
    Given the following customers with parameter type:
      | John  | Doe     |
      | David | Beckham |
    When customer 'Bruce' 'Springsteen' is added
    Then the customer 'Bruce' 'Springsteen' is added to the customer list


In the implementation of the step definition, you notice that the argument is not a DataTable anymore, but a list of Customer.

Java
 
@Given("the following customers with parameter type:")
public void the_following_customers_with_parameter_type(List<Customer> customers) {
 
    for (Customer customer : customers) {
        customer_firstname_lastname_is_added(customer.getFirstName(), customer.getLastName());
    }
}


Conclusion

In this blog, you learned how to integrate Cucumber with a Spring Boot application and several ways to pass arguments to your step definitions - a powerful feature of Cucumber!

Spring Integration Cucumber (software) Java (programming language) Spring Boot Testing

Published at DZone with permission of Gunter Rotsaert, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Automating Cucumber Data Table to Java Object Mapping in Your Cucumber Tests
  • Integrate Cucumber in Playwright With Java
  • Keep Your Application Secrets Secret
  • Testcontainers With Kotlin and Spring Data R2DBC

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!