TDD : Test Data Preparation and Maintenance Tips

While writing a test, we generally struggle with generating the test data for our test. A major portion of our test code get covered with code for generating test data and sometimes those test data became very difficult to manage. This article is about how we can resolve such issues with a different approach.

For example, we want to test the save method of a java class EmployeeDAO which takes an Employee object as parameter.

EmployeeDAO.java

public class EmployeeDAO {
    public boolean save(Employee employee) {
      // some code here
    }
}

And Employee class has the following structure.

Employee.java

public class Employee{
    private String firstName;
    private String lastName;
    private int age;
    private String email;
    private Address address;

   // getters & setters
}

Address.java

public class Address {
    private String line1;
    private String line2;
    private String line3;
    private String line4;

    // getters & setters
}

So in our test code to test save method of EmployeeDAO, we need to build an Employee object (as test data) as below to pass it as parameter to the save method.

EmployeeDAOTest.java

public EmployeeDAOTest {
    @Test
    public void saveTest(){
        // Generate Test Data
        Employee employee = new Employee();
        employee.setFirstName("testFirstName");
        employee.setLastName("testLastName");
        employee.setAge(19);
        employee.setEmail("test@mail.com");

        Address address = new Address();
        address,setLine1("testLine1");
        address.setLine2("testLine2");
        address.setLine3("testLine3") ;
        address.setLine4("testLine4");

        employee.setAddress(address);

        // Create the object of class under test and invoke
        EmployeeDAO employeeDAO = new EMployeeDAO();
        boolean result = employeeDAO.save(employee);

        // Code To Assert Result
    }
}

Here we had to write around 11 lines of code in our test method to generate the test data Employee, which is more than 90% of the test code. And it will be worse when the test data is more complex. And it also makes the maintenance and readability of the test code and test data difficult. So following is an example of how we can generate and maintain test data in a better way.

Step-1 : Instead of keeping the test data in our test code lets keep it outside in a file in json format.

employee.json

{
"firstName" : "TestFirstName",
"lastName" : "TestLastName",
"age" : 19,
"email" : "test@mail.com",
"address" : {
    "line1" : "TestLine1",
    "line2" : "TestLine2",
    "line3" : "TestLine3",
    "line4" : "TestLine4"
    }
}

Step 2 : Add any JSON API to your class path to create java object from JSON content. Here I used jackson.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.3.2</version>
    <scope>test</scope>
</dependency>

Step 3 : In your test method read the json file to generate test object using the API.

public EmployeeDAOTest {
    @Test
    public void saveTest(){
        // Generate Test Data
        Employee employee = new ObjectMapper().readValue(
                    getClass().getResourceAsStream("/employee.json"),
                    Employee.class);

        // Create the object of class under test and invoke
        EmployeeDAO employeeDAO = new EMployeeDAO();
        boolean result = employeeDAO.save(employee);

        // Code To Assert Result
    }
}

So with the second approach , just 1 line of code is required to generate the test object, instead of 11 lines of code, which make my test code cleaner and smaller. Cleaner and smaller code results in making the test code easy to read, understand and maintain. And keeping test data in a file in json format makes easier to read, visualize and maintain.

Happy Testing !!!