Writing Custom DbUnit Data Types: Text Array

After we have finished this lesson, we:

  • Can write a custom DbUnit data type which supports PostgreSQL text arrays.
  • Know how we can ensure that DbUnit uses our custom data type.

Get the source code from Github

Creating Our DbUnit Data Set

We have to write integration tests for a repository which reads information from the products table. When we initialize our database into a known state, we have to set the value of the tags column which contains a text array. When we configure the value of this column in our DbUnit data set, the most obvious choice is to use a comma-separated value which specifies the tags of a product.

After we have created our DbUnit data set, it looks as follows:

1<dataset>
2    <products id="1"
3              product_description="Product description"
4              product_name="Product name"
5              tags="example,product"
6    />
7</dataset>

Next, we will find out how we can create a custom DbUnit data type which supports text arrays.

Writing Our Custom DbUnit Data Type

When we want to create a custom DbUnit data type, we have to create a new data type class and implement the typeCast() method of the DataType class. We can implement this method by following these steps:

  1. If the value given as a method parameter is a String object, transform the value into a String array and return the created array.
  2. If the value given as a method parameter isn’t a String object, throw a new exception.

After we have implemented the typeCast() method, the source code of our data type class looks as follows:

 1import org.dbunit.dataset.datatype.AbstractDataType;
 2import org.dbunit.dataset.datatype.TypeCastException;
 3
 4public class StringArrayDataType extends AbstractDataType {
 5
 6    public StringArrayDataType(String name, int sqlType) {
 7        super(name, sqlType, String.class, false);
 8    }
 9
10    @Override
11    public Object typeCast(Object value) throws TypeCastException {
12        if (value instanceof String) {
13            return ((String) value).split(",");
14        }
15
16        throw new IllegalArgumentException(String.format(
17                "Unsupported type. Expected String but was: %s",
18                value.getClass().getName()
19        ));
20    }
21}

Let’s move on and find out how we can enable our custom DbUnit data type.

Enabling Our Custom DbUnit Data Type

When we want to ensure that DbUnit uses our custom data type, we have create a new data type factory class and implement the createDataType() method of the IDataTypeFactory interface. We can implement this method by following these steps:

  1. If the data type of the processed column is text array, return a new StringArrayDataType object.
  2. If the data type of the processed column is an unsupported array type, throw a new exception.
  3. Invoke the createDataType() method of the super class and return the returned data type object.

After we have implemented the createDataType() method, the source code of our data type factory class looks as follows:

 1import org.dbunit.dataset.datatype.DataType;
 2import org.dbunit.dataset.datatype.DataTypeException;
 3import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
 4
 5import java.sql.Types;
 6
 7public class CustomPostgreSQLDataTypeFactory extends PostgresqlDataTypeFactory {
 8
 9    private static final String SQL_TYPE_NAME_TEXT_ARRAY = "_text";
10
11    @Override
12    public DataType createDataType(int sqlType,
13                                   String sqlTypeName,
14                                   String tableName,
15                                   String columnName) throws DataTypeException {
16        if (sqlType == Types.ARRAY) {
17            if (sqlTypeName.equals(SQL_TYPE_NAME_TEXT_ARRAY)) {
18                return new StringArrayDataType(sqlTypeName, sqlType);
19            }
20            throw new IllegalArgumentException(
21                    "Unsupported array type: " + sqlTypeName
22            );
23        }
24
25        return super.createDataType(sqlType,
26                sqlTypeName,
27                tableName,
28                columnName
29        );
30    }
31}

We can now implement a custom DbUnit data type which supports PostgreSQL text arrays. Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us two things:

  • When we set the value of a database column which contains a text array, we should use a comma-separated value in our DbUnit data set.
  • When we ensure that DbUnit uses our custom data type, we have to ensure that our data type factory returns a new StringArrayDataType object if the data type of the processed column is text array.

Get the source code from Github