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
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Translating OData Queries to MongoDB in Java With Jamolingo
  • Jakarta EE 12 M2: Entering the Data Age of Enterprise Java
  • Prototype for a Java Database Application With REST and Security
  • Build a REST API With Just 2 Classes in Java and Quarkus

Trending

  • The Agentic Agile Office: Streamlining Enterprise Agile With Autonomous AI Agents
  • Compliance Automated Standard Solution (COMPASS), Part 11: Compliance as Code, the OSCAL MCP Server Way
  • Identity in Action
  • Alternative Structured Concurrency
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Data-Driven API Testing in Java With REST Assured and TestNG: Part 3

Data-Driven API Testing in Java With REST Assured and TestNG: Part 3

Learn how to perform data-driven API automation testing with Rest-Assured using CSV Files and TestNG's @DataProvider annotation.

By 
Faisal Khatri user avatar
Faisal Khatri
DZone Core CORE ·
Mar. 25, 26 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
3.2K Views

Join the DZone community and get the full member experience.

Join For Free

Data-driven testing enables testers to execute the same test logic with multiple sets of input data, improving coverage and reliability with minimal effort. By combining CSV files with TestNG’s @DataProvider annotation, test data can be easily separated from the test logic. This approach enables maintainability and makes test automation more scalable and flexible.

This article explains how to implement data-driven testing with CSV files and TestNG in a clear, practical, and easy-to-follow manner.

Data-Driven Testing Using TestNG’s @DataProvider Annotation and CSV Files

The setup and configuration remain the same as discussed in the earlier tutorial. Additionally, the following dependency for Jackson-dataformat-csv should be added to the pom.xml to handle the CSV files.

XML
 
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-csv</artifactId>
    <version>2.21.0</version>
</dependency>


The POST /addOrder API of the RESTful e-commerce demo application will be used for the demonstration. The schema for the API is given below:

JSON
 
[
  {
    "user_id": "string",
    "product_id": "string",
    "product_name": "string",
    "product_amount": 0,
    "qty": 0,
    "tax_amt": 0,
    "total_amt": 0
  }
]
Available on GitHub


Creating a POJO Class

The following POJO class should be created to map the CSV file data to the data provider:

Java
 
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    @JsonProperty ("user_id")
    private String userId;
    @JsonProperty ("product_id")
    private String productId;
    @JsonProperty ("product_name")
    private String productName;
    @JsonProperty ("product_amount")
    private int    productAmount;
    private int    qty;
    @JsonProperty ("tax_amt")
    private int    taxAmt;
    @JsonProperty ("total_amt")
    private int    totalAmt;
}


Code Walkthrough

The Order POJO simplifies reading the CSV file by mapping each row to a single object, with each column in the row mapped to its corresponding class variable. Using a POJO helps remove hard-coded mapping logic by allowing CSV parsing libraries to automatically bind column names to class fields based on annotations or naming conventions.

Instead of manually extracting values by column index (for example, row[0], row[1], etc.), the POJO maps each CSV column directly to the corresponding property.

The @Getter and @Setter annotations automatically create getter and setter methods for all fields during compilation. The @AllArgsConstructor annotation enables quick creation of fully initialized objects, which is useful when manually creating test data.

The @NoArgsConstructor annotation generates a default constructor with no parameters. Without it, the library may fail to create instances of the POJO during CSV mapping. In this Order class, the @NoArgsConstructor ensures automatic object creation when reading data from CSV files.

If you’d like to dive deeper into testing POST requests with REST Assured in Java, check out this detailed guide.

Creating a Utility to Read CSV Files

The following CSV file will be used to perform data-driven testing:

Plain Text
 
user_id,product_id,product_name,product_amount,qty,tax_amt,total_amt
"U001","P1001","Laptop",850,1,42,892
"U002","P1002","Smartphone",600,2,60,1260
"U003","P1003","Headphones",120,3,18,378
"U004","P1004","Keyboard",75,2,7,157
"U005","P1005","Mouse",40,4,8,168
"U006","P1006","Monitor",300,1,15,315
"U007","P1007","Tablet",450,2,45,945
"U008","P1008","Printer",200,1,10,210
"U009","P1009","Webcam",90,3,13,283
"U010","P1010","Speaker",150,2,15,315


Let’s create a utility method to read CSV files from the ‘src/test/resources/` folder.

Java
 
public class CSVReader {
    @SneakyThrows
    public static List<Order> getOrderData (String filename) {
        InputStream inputStream = CSVReader.class.getClassLoader ()
            .getResourceAsStream (filename);
        if (inputStream == null) {
            throw new RuntimeException ("File not found: " + filename);
        }

        CsvSchema schema = CsvSchema.emptySchema ()
            .withHeader ();

        MappingIterator<Order> iterator;
        try {
            iterator = new CsvMapper ().readerFor (Order.class)
                .with (schema)
                .readValues (inputStream);

        } catch (IOException e) {
            throw new RuntimeException (e);
        }
        return iterator.readAll ();
    }
}


Code Walkthrough

The getOrderData() method is static and reads a CSV file, returning a list of Order objects. The following steps explain the CSV file reading process:

  • Loading the CSV file: It loads the CSV file from the resources folder (src/test/resources/) using the class loader. If the file is not found, it throws a RuntimeException.
Java
 
CsvSchema schema = CsvSchema.emptySchema ()
            .withHeader ();


  • Defining the CSV schema: The above code statement defines the CSV schema for Jackson’s parser. The emptySchema().withHeader() tells Jackson to use the first row as column headers to map them to the fields in the Order POJO.
Java
 
MappingIterator<Order> iterator;
try {
    iterator = new CsvMapper ().readerFor (Order.class)
        .with (schema)
        .readValues (inputStream);

} catch (IOException e) {
    throw new RuntimeException (e);
}
return iterator.readAll()


  • Reading the CSV file: The CSV file is read using the CsvMapper from the Jackson-dataformat-csv library. It maps each row to the Order object using code readerFor(Order.class).with(schema). The code readValues(inputStream) creates a MappingIterator<Order> that allows iterating over all rows of the CSV. If any I/O error occurs while reading the file, it is caught and rethrown as a RuntimeException to simplify error handling. Finally, the iterator reads all the remaining rows and returns them as a List<Order>.

Creating a DataProvider Method

The following data provider method returns the test data from the CSV file as Iterator<Object[]>, which is further consumed by the test.

Java
 
@DataProvider (name = "orderData")
    public Iterator<Object[]> getOrders () {
        List<Order> orderList = CSVReader.getOrderData ("order_data.csv");
        return orderList.stream ()
            .map (order -> new Object[] { order })
            .iterator ();
    }


Code Walkthrough

The getOrders() method reads test data from the “order_data.csv” file. It loads all records as a list of Order objects using the CSVReader utility. The stream operation converts each Order into an Object[] format, and then returns an Iterator, allowing TestNG to efficiently run the same test multiple times with different input data.

Writing the API Automation Test

Let’s write the test for the POST /addOrder API that creates orders using the test data supplied from the CSV files using the data provider:

Java
 
@Test (dataProvider = "orderData")
    public void testCreateOrder (Order order) {
        List<Order> orderList = List.of (order);
        given ().contentType (ContentType.JSON)
            .when ()
            .log ()
            .all ()
            .body (orderList)
            .post ("http://localhost:3004/addOrder")
            .then ()
            .log ()
            .all ()
            .statusCode (201)
            .and ()
            .assertThat ()
            .body ("message", equalTo ("Orders added successfully!"));

    }


The testCreateOrder() method uses the orderData DataProvider to run the same test multiple times, each time with a different Order object from the CSV file.

Before making the POST request, each order is wrapped inside a List using “List.of(order)” as the POST /addOrder API expects a list of orders in the request body. The test then verifies the response by checking that the status code is 201 and confirming that the success message “Orders added successfully” is returned.

Checkout  this detailed tutorial on How to Perform Response Verification in REST-Assured Java for API Testing.

Test Execution

When the test is executed, TestNG automatically runs the testCreateOrder() method multiple times, each time using a different set of test data read from the CSV file through the orderData DataProvider.

Test execution


Summary

Using CSV files with TestNG’s DataProvider offers a simple and effective way to implement data-driven testing by keeping test data separate from test logic. This approach makes test cases easier to maintain, improves readability, and allows testers to update or extend test scenarios without modifying the code.

Happy testing!

API testing REST TestNG Java (programming language)

Published at DZone with permission of Faisal Khatri. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Translating OData Queries to MongoDB in Java With Jamolingo
  • Jakarta EE 12 M2: Entering the Data Age of Enterprise Java
  • Prototype for a Java Database Application With REST and Security
  • Build a REST API With Just 2 Classes in Java and Quarkus

Partner Resources

×

Comments

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

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

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 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook