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

  • Architecting a Comprehensive Testing Framework for API and UI Testing
  • Cypress API Testing: A Detailed Guide
  • Which API Testing Strategy Should You Use? Manual vs. Automated
  • Cypress.io — The Rising Future of Web Automation Testing

Trending

  • Orchestrating Microservices with Dapr: A Unified Approach
  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  • Manual Sharding in PostgreSQL: A Step-by-Step Implementation Guide
  • Cosmos DB Disaster Recovery: Multi-Region Write Pitfalls and How to Evade Them
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. API Testing With Cucumber

API Testing With Cucumber

Testing APIs in a microservices environment can be a challenging task. In this tutorial, we will learn to address it in BDD-style testing using Cucumber.

By 
Randhir Singh user avatar
Randhir Singh
·
Sep. 25, 21 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
14.7K Views

Join the DZone community and get the full member experience.

Join For Free

An API represents a set of rules that enables services to communicate with each other. It is important to have a shared understanding of the API by the stakeholders. Behavior Driven Development (BDD) allows us to describe behaviors that are understandable to domain experts, testers, and developers through examples. A well-written example serves to represent a balanced view of competing concerns -

  • Shared understanding. An example can be shared among API stakeholders to promote communication and understanding.
  • Tests.  Implement the example as an automated test to check the functionality of the API.
  • Documentation. An example can be used by anyone to understand the system.

BDD is a very apt tool to test APIs. We will use Cucumber that supports BDD to test APIs developed in Java. One advantage of doing so is that the Java developer who implemented the API does not have to learn a new language to test it.

Test Automation Project

We have to set up a Java Maven Project that contains our BDD scenarios that we are going to automate. Include the following dependencies.

  • Cucumber libraries to allow us to write BDD scenarios in Gherkin syntax
  • Cucumber Pico container for dependency injection
  • Rest Assured to test and validate REST calls
  • JSON to handle JSON documents
  • Apache Log4J to log requests and responses
  • JUnit to allow us to run BDD scenarios as JUnit test
XML
 
    <dependencies>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-core</artifactId>
            <version>6.6.0</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>6.6.0</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>gherkin</artifactId>
            <version>15.0.2</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-jvm-deps</artifactId>
            <version>1.0.6</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>6.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-picocontainer</artifactId>
            <version>6.11.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-iostreams</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20210307</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

Project Organization

The picture shows a sample project organization. It consists of the following folders under test.

  • Context - Contains utilities to hold context to help communication among steps
  • Microservice - Each microservice can have a folder to contain scenarios for API exposed by it. Within each microservice folder, create the following folders
    • features - Holds feature files
    • steps - Implements steps from feature files
    • dev/qa/prod - Environment variables for different environments where APIs are hosted
    • common - Implement steps common among features
  • Testrunner - Runner for Cucumber tests
  • Util - Contains utilities

Test automation

Gherkin Basics

Cucumber understands Gherkin, a structured natural language syntax based upon the Given/When/Then format. Gherkin allows us to write business readable API specifications that can also be used as automated tests. It is written in feature files which are plain text files with .feature extension.

Each feature file contains one or more scenarios. Each scenario is made up of one or more steps. Each step starts with one of five keywords: Given, When, Then, And, But. Given, When, Then introduce respectively the context, action, and outcome section of a scenario. And But are conjunctions that continue the preceding section. 

A sample test is shown below. A scenario should contain enough information to balance among its key features -  shared understanding, test, and documentation.

Gherkin
 
@Tag
Feature: Perform full demographic verification of a person

  Background:
    Given caller presents a valid access token

  Scenario: Perform full demographic verification with valid credentials
    Given a person with full demographic details
      | adhar_id            | 123456789        |
      | full_name           | John Doe         |
      | dob                 | 31/12/1990       |
      | phone_no            | 999999999999     |
      | email               | john@doe.com     |
    And the match threshold is set to 1.0
    When request is submitted for full demographic verification
    Then verify that the HTTP response is 200
    And a transaction id is returned

Each step in the feature file needs to be implemented in Java. In the step definition below, we

  • Read the configuration for an environment
  • Make REST call using Rest Assured
  • Save the response of the call in the context for the benefit of other steps
Java
 
public class Microservice1Steps {

    private final World world;
    private final Properties envConfig;
    private RequestSpecification request;

    public Microservice1Steps(World world) {
        this.world = world;
        this.envConfig = World.envConfig;
        this.world.featureContext = World.threadLocal.get();
    }

    @Before
    public void setUp() {
        request = RequestSpecificationFactory.getInstance(world);
    }

    @Given("caller presents a valid access token")
    public void getOAuth2Token() {
        String grantType = envConfig.getProperty("microservice1-grant_type");
        String clientId = envConfig.getProperty("microservice1-client_id");
        String clientSecret = envConfig.getProperty("microservice1-client_secret");
        String accessTokenUrl = envConfig.getProperty("microservice1-access_token_url");

        String body = String.format("grant_type=%s&client_secret=%s&client_id=%s", grantType, clientSecret, clientId);

        RequestSpecification request = RequestSpecificationFactory.getInstanceOAuth2();

        Response response = request
                .accept(ContentType.URLENC)
                .body(body)
                .post(accessTokenUrl);

        String responseString = response.then().extract().asString();
        String accessToken = new JSONObject(responseString).getString("access_token");

        world.scenarioContext.put("accessToken", accessToken);
    }
}

A set of scenarios may be run as a JUnit test:

Shell
 
mvn test -Denv=local -Dcucumber.filter.tags="@Tag"

Tag selects a set of tests to run and -Denv selects the environment to run the tests on.

The complete project is available on my GitHub.

Conclusion

In this article, we learned why BDD is a natural fit for testing API as it enhances shared understanding, tests, and documentation of the API. For Java developers, a Maven project with Cucumber libraries is easy to set up to add scenarios and test them.

API Cucumber (software) Testing API testing file IO

Opinions expressed by DZone contributors are their own.

Related

  • Architecting a Comprehensive Testing Framework for API and UI Testing
  • Cypress API Testing: A Detailed Guide
  • Which API Testing Strategy Should You Use? Manual vs. Automated
  • Cypress.io — The Rising Future of Web Automation Testing

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!