Test Conventions
Overview
This page covers writing dbUnit’s own test suite as a contributor. Looking for how to
use IDatabaseTester/DBTestCase in your own project’s tests? See
Test Integration instead — that page is about testing with
dbUnit; this one is about testing dbUnit itself.
Test Types & Suffixes
<ClassName>Test— a unit test. No database required; runs in the normal Maventestphase via Surefire.<ClassName>IT— an integration test. Any test that requires a database to work is an integration test, even if the logic under test looks simple. Runs in the Mavenintegration-testphase via Failsafe. See Integration Tests for how to run these against a specific database.
Test Method Naming
test<MethodName>_<StartingStateConditions>_<AssertedOutcome>. For example, from
TableFormatterTest:
void testFormatSimpleTable_withTwoRows_returnsFormattedTableString() throws ExceptionThe method under test is formatSimpleTable (conceptually — TableFormatter.format),
the starting condition is "with two rows," and the asserted outcome is "returns a
formatted table string."
Coverage Expectation
Every change needs unit test coverage added or updated to cover it — proving a bug fix actually fixes the reported problem, and proving a new feature works. Tests also carry long-term value beyond the immediate change: they prove future changes don’t break the behavior they cover.
Assertions
Prefer AssertJ. Prefer asserting the actual object against an expected object as a
whole, rather than field-by-field or value-by-value. The same TableFormatterTest
example above does this correctly — it builds one expected string and asserts the
whole thing in a single isEqualTo, rather than checking fragments of the output
individually:
final String expected =
"****** table: MY_TABLE ** row count: 2 ******\n"
+ "COL1 |COL2 |\n"
+ "====================|====================|\n"
+ "my string value |39284.1 |\n"
+ "my string value2 |2 |\n";
assertThat(actual).isEqualTo(expected);Use an .as() for the test fail message on an assertion
and end the message with a period
so it doesn’t combine with the subsequent JUnit message,
e.g. assertThat(actual.getMessage()).as("Should have null message.").isNull();.
Test Doubles: Composition Over Inheritance
When a test needs to spy on or intercept calls to a real collaborator — most often an
IMetadataHandler, IDataTypeFactory, or
similar dbUnit extension-point interface — wrap it, don’t subclass a concrete
implementation. A test double that extends a specific vendor class (e.g.
H2MetadataHandler) only works while the connection under test uses that one vendor,
and Java’s single inheritance means it cannot also extend a second vendor’s class if
that ever changes. A test double that implements the interface and holds a delegate
field, forwarding every method to it except the one or two being spied on, stays correct
regardless of which concrete implementation the connection under test actually uses:
private static class TestMetadataHandler implements IMetadataHandler
{
private final IMetadataHandler delegate;
private final Set<String> schemaSet = new HashSet<>();
TestMetadataHandler(final IMetadataHandler delegate)
{
this.delegate = delegate;
}
@Override
public ResultSet getTables(final DatabaseMetaData metaData,
final String schemaName, final String[] tableType) throws SQLException
{
schemaSet.add(schemaName);
return delegate.getTables(metaData, schemaName, tableType);
}
// ...every other IMetadataHandler method delegates to `delegate` unchanged.
}See DatabaseDataSet_MultiSchemaTest for the full example: it wraps whichever
IMetadataHandler the connection under test is actually configured with
(H2MetadataHandler, in that test’s case) instead of extending it, so the test stays
correct even if H2 support’s implementation changes, and would work unmodified if the
test ever moved to a different vendor.
Fixed Test Timezone
Surefire and Failsafe both force -Duser.timezone=Europe/Berlin on every test run
(confirmed in `pom.xml’s plugin configuration) — so timestamp/timezone-sensitive
behavior is exercised consistently in CI regardless of the runner’s own locale. A test
launched directly from an IDE skips this unless you configure the run configuration to
match. See Building's Quality Gates section for the mechanics.
Java Style
This page covers test-specific conventions only. For general Java style, see Java Style & Tooling.


