Writing Custom DbUnit Data Types: JSON
After we have finished this lesson, we:
- Can write a custom DbUnit data type which supports the
jsondata type of the PostgreSQL database. - Know how we can ensure that DbUnit uses our custom data type.
This lesson assumes that:
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 reviews column which contains a JSON document. When we configure the value of this column in our DbUnit data set, the most obvious choice is to use the string representation of the JSON document.
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 reviews="[{"id": 1, "author": "Petri Kainulainen", "score": 5, "text": "Review"}]"
6 />
7</dataset>
Next, we will find out how we can create a custom DbUnit data type which supports the json data type of the PostgreSQL database.
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:
- If the value given as a method parameter is a
Stringobject, return the value given as a method parameter. - If the value given as a method parameter isn’t a
Stringobject, throw a new exception.
After we have overridden 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
4import java.sql.Types;
5
6public class JsonDataType extends AbstractDataType {
7
8 private final static String POSTGRESQL_TYPE_JSON = "json";
9
10 public JsonDataType() {
11 super(POSTGRESQL_TYPE_JSON, Types.OTHER, String.class, false);
12 }
13
14 @Override
15 public Object typeCast(Object value) throws TypeCastException {
16 if (value instanceof String) {
17 return value;
18 }
19
20 throw new IllegalArgumentException(String.format(
21 "Unsupported type. Expected String but was: %s",
22 value.getClass().getName()
23 ));
24 }
25}
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:
- If the data type of the processed column is
json, return a newJsonDataTypeobject. - 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
5public class CustomPostgreSQLDataTypeFactory extends PostgresqlDataTypeFactory {
6
7 private static final String SQL_TYPE_NAME_JSON = "json";
8
9 @Override
10 public DataType createDataType(int sqlType,
11 String sqlTypeName,
12 String tableName,
13 String columnName) throws DataTypeException {
14 if (sqlTypeName.equals(SQL_TYPE_NAME_JSON)) {
15 return new JsonDataType();
16 }
17
18 return super.createDataType(sqlType,
19 sqlTypeName,
20 tableName,
21 columnName
22 );
23 }
24}
We can now implement a custom DbUnit data type which supports the json data type of the PostgreSQL database. 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 JSON document, we should use the string representation of the JSON document 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
JsonDataTypeobject if the data type of the processed column isjson.