DbUnit Best Practices: Using Test Data in Our Java Code

After we have finished this lesson, we

  • Understand why it might not be a good idea to declare constants in our test classes.
  • Know how we can declare constants in a clean way and use these constants in our test classes.

Why Should We Care?

We have already learned how we can insert test data into our database and write assertions for the data that is found from our database. However, because we want to write clean integration tests, we have to also know how we can use the same test data in our integration test classes and DbUnit data sets.

In other words, we have to figure out a clean way to create the input data that is provided to the tested feature or method AND write assertions for the data that is returned by the tested feature or method.

Let’s find out why the obvious answer isn’t always a good choice.

The Problem of Declaring Constants In Our Test Classes

The obvious answer is to add constants into our test class. For example, after we have declared the required constants in our test class, its source code could look as follows:

1public class TaskControllerTest {
2
3    private static final Long TASK_ID = 1L;
4	private static final Long TASK_CREATOR_ID = 1L;
5	private static final String TASK_DESCRIPTION = "Write about test data.";
6	private static final String TASK_TITLE = "Write lesson";
7	private static final TaskStatus TASK_STATUS = TaskStatus.OPEN;
8}

This is a good choice if the TaskControllerTest class is the only test class that needs this test data. However, because we should reuse our test data when we write integration tests, the odds are that multiple test classes need to access the same test data.

If we add these constants into all test classes that require this test data, we create a test suite that is hard to maintain. The problem is that when we make changes to our test data, we have to remember to:

  • Modify the DbUnit data sets.
  • Update the constants found from the test classes that use the modified test data.

It’s clear that we shouldn’t use this option if multiple test classes need to access the same test data. Let’s find out how we can solve this problem by using so called constant classes.

Constant Classes to the Rescue

As you probably figured out, a constant class is a class that declares constants. When we create these classes, we want to fulfill these two goals:

  • We want to ensure that our test code declares the required constants only once because this makes our tests easy to maintain.
  • We want to create a “domain-specific language” for our test data because this makes our tests easy to read.

If we want to create a constant class that contains the information of one task, we have to follow these steps:

First, we have to create the constant class that contains all tasks found from the database. The source code of this class looks as follows:

1public class Tasks {
2
3}
I name these constant classes by using the plural noun of the entity in question. I follow this rule mainly because it helps me to find the relevant constants when I am writing integration tests for my application.

Second, we have to add a public and static inner class into our constant class. This class contains the information of a single task. After we have created this inner classes, the source code of our constant class looks as follows:

1public class Tasks {
2
3	public static class WriteLesson {
4
5	}
6}
We must give a proper name for our static inner class because it helps us to create a “domain-specific language” for our test data.

Third, we have to add the required constants into the WriteLesson class. These constants contain the information that is found from our DbUnit data sets. After we have declared the required constants, the source code of our constant class looks as follows:

 1public class Tasks {
 2
 3	public static class WriteLesson {
 4
 5	    public static final Long ID = 1L;
 6	    public static final Long CREATOR_ID = 1L;
 7	    public static final String DESCRIPTION = "Write about test data.";
 8	    public static final String TITLE = "Write lesson";
 9		public static final TaskStatus STATUS = TaskStatus.OPEN;
10	}
11}

We are done. We have just created a constant class that declares the constants required by our integration tests. If we need to make changes to our test data, we have to make these changes only to our DbUnit data sets and to relevant constant classes. This makes our integration tests easier to maintain.

Also, even though our example is quite simple, it should demonstrate that we can create a domain-specific language for our test data by giving proper names to the required classes and to the constants that specify the actual test data.

Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us three things:

  • We shouldn’t add constants into our test classes if multiple test classes need to use the same test data.
  • Constant classes make our integration tests easier to maintain because we have to declare the required constants only once.
  • We can use constant classes for creating a “domain-specific language” for our test data.