Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</properties>

<body>
<release version="3.4.1-SNAPSHOT" date="TBD" description="A documentation-site overhaul (new tutorials, 9 database vendor guides, a class-by-class Core Components reference, consolidated Filters/Datasets/Operations pages, and a new Developing DbUnit contributor section covering coding standards, commit/changelog requirements, and the GitHub workflow); an opt-in all-column sort for tables without a primary key; an opt-in sort-on-filtered-columns-only mode for DefaultPrepAndExpectedTestCase fixing false failures on tables with a generated/identity first column; MultiSchemaMySqlMetadataHandler for multi-schema MySQL connections; constructor-injected per-connection DatabaseConfig support for DataSourceDatabaseTester; new MariaDB support (MariaDbDataTypeFactory plus a Docker-backed IT profile); and multiple bug fixes including escape-pattern handling, primary-key filter fallback, empty-dataset DTD export, DatabaseDataSet initialization order, and a from-scratch clean-build pass across Javadoc doclint, Checkstyle, and compiler warnings">
<release version="3.4.1-SNAPSHOT" date="TBD" description="A documentation-site overhaul (new tutorials, 9 database vendor guides, a class-by-class Core Components reference, consolidated Filters/Datasets/Operations pages, and a new Developing DbUnit contributor section covering coding standards, commit/changelog requirements, and the GitHub workflow); an opt-in all-column sort for tables without a primary key; an opt-in sort-on-filtered-columns-only mode for DefaultPrepAndExpectedTestCase fixing false failures on tables with a generated/identity first column; an optional DefaultPrepAndExpectedTestCase FailureHandler for collecting every mismatch instead of failing fast; MultiSchemaMySqlMetadataHandler for multi-schema MySQL connections; constructor-injected per-connection DatabaseConfig support for DataSourceDatabaseTester; new MariaDB support (MariaDbDataTypeFactory plus a Docker-backed IT profile); and multiple bug fixes including escape-pattern handling, primary-key filter fallback, empty-dataset DTD export, DatabaseDataSet initialization order, and a from-scratch clean-build pass across Javadoc doclint, Checkstyle, and compiler warnings">
<action dev="jeffjensen" type="add" issue="840" system="github" due-to="jeffjensen">
Add repo-root README.adoc, rendered natively by GitHub via Asciidoctor, so the repository landing page shows a pitch, build/reproducible-build badges, a pointer to the "dbUnit in 5 Minutes" tutorial, and links to the documentation site, Maven coordinates, GitHub Discussions, and CONTRIBUTING.md instead of nothing.
</action>
Expand Down Expand Up @@ -230,6 +230,9 @@
<action dev="jeffjensen" type="add" issue="706" system="github" due-to="estebanjgarcia">
Add MariaDB support in a new org.dbunit.ext.mariadb package, separate from org.dbunit.ext.mysql since MariaDB is its own distinct, independently-branded product (mirroring how org.dbunit.ext.netezza stays independent of org.dbunit.ext.postgresql despite Netezza's Postgres lineage): MariaDbDataTypeFactory (extends MySqlDataTypeFactory to reuse its real, verified-shared type handling) declares "mariadb" as a valid database product, silencing the "might cause problems with the current database" warning, and recognizes MariaDB's native UUID (10.7+) and INET4/INET6 (10.10+) column types, which MariaDB Connector/J reports as SQL type OTHER with no MySQL equivalent; MariaDB's JSON type is a LONGTEXT alias and already worked via the inherited longtext handling. Add a mariadb-11-4 Maven profile and Docker-backed IT suite mirroring the existing mysql-9-20 profile, and a dedicated databases/mariadb.adoc site page (with its own navigation entry) instead of folding coverage into the MySQL page. Along the way, found and documented that MariaDB Connector/J, unlike MySQL Connector/J, has no nullCatalogMeansCurrent-equivalent default: an unfiltered DatabaseMetaData#getTables() call leaks information_schema/performance_schema tables into dbUnit's table map, surfacing as a SQLSyntaxErrorException the moment an operation like DELETE_ALL touches one of them, unless MySqlMetadataHandler is registered or nullCatalogMeansCurrent=true is added to the JDBC URL.
</action>
<action dev="jeffjensen" type="add" issue="865" system="github" due-to="jeffjensen">
Add DefaultPrepAndExpectedTestCase.setFailureHandler(FailureHandler), letting verifyData() use a caller-supplied FailureHandler such as DiffCollectingFailureHandler instead of the default fail-fast DefaultFailureHandler; unset (null) keeps the pre-existing default behavior unchanged.
</action>
</release>
<release version="3.4.0" date="Jul 28, 2026" description="Test-suite hardening (un-skip and strengthen dozens of disabled/no-op tests); add CachingConnectionProvider and reduce DefaultPrepAndExpectedTestCase's per-test connection churn; pin identifier case-folding to Locale.ENGLISH for Turkish-locale correctness; and a broad set of correctness fixes across export formats (XML, YAML, CSV, XLS, Ant), TimestampDataType timezone handling, InsertOperation/TransactionOperation, and resource-leak cleanups">
<action dev="jeffjensen" type="fix" issue="797" system="github" due-to="jeffjensen">
Expand Down
70 changes: 67 additions & 3 deletions src/main/java/org/dbunit/DefaultPrepAndExpectedTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

import org.dbunit.assertion.FailureHandler;
import org.dbunit.assertion.comparer.value.ValueComparer;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
Expand Down Expand Up @@ -67,6 +68,13 @@
* cleanupData() does not close a connection other tests still expect to
* reuse; the provider's owner is then responsible for closing it once,
* itself, when the whole run finishes.
* <p>
* The {@code verifyData()} method hands assertion failures to
* {@link org.dbunit.assertion.DefaultFailureHandler} by default, which throws
* on the first mismatch found. Set {@link #setFailureHandler(FailureHandler)}
* to, for example, a {@link org.dbunit.assertion.DiffCollectingFailureHandler}
* to collect every {@link org.dbunit.assertion.Difference} instead; that is
* not the default since most tests want to keep failing fast.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
*
* @see "org.dbunit.DefaultPrepAndExpectedTestCaseDiIT, a composition-based (DI) usage example in the test sources"
* @see "org.dbunit.DefaultPrepAndExpectedTestCaseExtIT, an inheritance-based usage example in the test sources"
Expand Down Expand Up @@ -127,6 +135,22 @@ public class DefaultPrepAndExpectedTestCase extends DBTestCase
private ExpectedDataSetAndVerifyTableDefinitionVerifier expectedDataSetAndVerifyTableDefinitionVerifier =
new DefaultExpectedDataSetAndVerifyTableDefinitionVerifier();

/**
* FailureHandler for verifyData()'s assertion failures. Null (the
* default) leaves compareData() using
* {@link org.dbunit.Assertion#assertWithValueComparer(ITable, ITable, Column[], ValueComparer, Map)}'s
* own {@link org.dbunit.assertion.DefaultFailureHandler}, configured with
* the additionalColumnInfo computed by {@link #makeAdditionalColumnInfo};
* that default is intentional so most tests keep failing fast on the
* first mismatch. Set this, for example to a
* {@link org.dbunit.assertion.DiffCollectingFailureHandler}, only when a
* test needs to collect every {@link org.dbunit.assertion.Difference}
* instead.
*
* @since 3.4.1
*/
private FailureHandler failureHandler;

final TableFormatter tableFormatter = new TableFormatter();

/** Create new instance. */
Expand Down Expand Up @@ -1067,6 +1091,11 @@ private void logSortedTable(final String tableTypeName,

/**
* Compare the tables, enables easy overriding.
* <p>
* Uses {@link #failureHandler} when set; otherwise defers to
* {@link Assertion#assertWithValueComparer(ITable, ITable, Column[], ValueComparer, Map)}'s
* own {@link org.dbunit.assertion.DefaultFailureHandler}, configured with
* additionalColumnInfo.
*
* @param expectedTable the table containing all expected results.
* @param actualTable the table containing all actual results.
Expand All @@ -1081,9 +1110,17 @@ protected void compareData(final ITable expectedTable,
final Map<String, ValueComparer> columnValueComparers)
throws DatabaseUnitException
{
Assertion.assertWithValueComparer(expectedTable, actualTable,
additionalColumnInfo, defaultValueComparer,
columnValueComparers);
if (failureHandler == null)
{
Assertion.assertWithValueComparer(expectedTable, actualTable,
additionalColumnInfo, defaultValueComparer,
columnValueComparers);
} else
{
Assertion.assertWithValueComparer(expectedTable, actualTable,
failureHandler, defaultValueComparer,
columnValueComparers);
}
}

/**
Expand Down Expand Up @@ -1424,6 +1461,33 @@ public void setExpectedDataSetAndVerifyTableDefinitionVerifier(
expectedDataSetAndVerifyTableDefinitionVerifier;
}

/**
* Get the failureHandler.
*
* @see #failureHandler
*
* @return The failureHandler.
* @since 3.4.1
*/
public FailureHandler getFailureHandler()
{
return failureHandler;
}

/**
* Set the failureHandler.
*
* @see #failureHandler
*
* @param failureHandler
* The failureHandler to set.
* @since 3.4.1
*/
public void setFailureHandler(final FailureHandler failureHandler)
{
this.failureHandler = failureHandler;
}

/**
* {@link IDatabaseTester} that runs setUp/tearDown operations against a
* connection supplied by the given {@link Callable} instead of calling
Expand Down
68 changes: 68 additions & 0 deletions src/test/java/org/dbunit/DefaultPrepAndExpectedTestCaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.sql.Connection;

import org.dbunit.assertion.DbComparisonFailure;
import org.dbunit.assertion.DiffCollectingFailureHandler;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.MockDatabaseConnection;
Expand Down Expand Up @@ -515,6 +516,73 @@ void testVerifyData_withTurkishDefaultLocale_matchesAsciiIColumns()
.doesNotThrowAnyException();
}

@Test
void testGetFailureHandler_withDefaultConfiguration_returnsNull()
{
assertThat(tc.getFailureHandler())
.as("Default must be null so verifyData() keeps using"
+ " Assertion's own default FailureHandler, matching"
+ " pre-existing behavior for callers who have not"
+ " configured a custom FailureHandler.")
.isNull();
}

@Test
void testVerifyData_withMismatchAndNoFailureHandlerConfigured_throwsError()
throws Exception
{
final Column[] columns = {new Column("COL1", DataType.VARCHAR)};

final DefaultTable expectedTable =
new DefaultTable("TEST_TABLE", columns);
expectedTable.addRow(new Object[] {"expected"});

final DefaultTable actualTable =
new DefaultTable("TEST_TABLE", columns);
actualTable.addRow(new Object[] {"actual"});

final Throwable thrown = catchThrowable(() -> tc.verifyData(
expectedTable, actualTable, null, null, null, null));

assertThat(thrown)
.as("Without a configured FailureHandler, verifyData() must"
+ " keep failing fast on the first mismatch, matching"
+ " pre-existing behavior.")
.isInstanceOf(DbComparisonFailure.class);
}

@Test
void testVerifyData_withMismatchAndDiffCollectingFailureHandlerConfigured_collectsDifferenceInsteadOfThrowing()
throws Exception
{
final Column[] columns = {new Column("COL1", DataType.VARCHAR)};

final DefaultTable expectedTable =
new DefaultTable("TEST_TABLE", columns);
expectedTable.addRow(new Object[] {"expected"});

final DefaultTable actualTable =
new DefaultTable("TEST_TABLE", columns);
actualTable.addRow(new Object[] {"actual"});

final DiffCollectingFailureHandler diffCollectingFailureHandler =
new DiffCollectingFailureHandler();
tc.setFailureHandler(diffCollectingFailureHandler);

assertThatCode(() -> tc.verifyData(expectedTable, actualTable, null,
null, null, null))
.as("A configured FailureHandler that collects"
+ " differences instead of throwing must be"
+ " used instead of the default fail-fast"
+ " handler.")
.doesNotThrowAnyException();

assertThat(diffCollectingFailureHandler.getDiffList())
.as("The mismatch must be recorded by the configured"
+ " DiffCollectingFailureHandler.")
.hasSize(1);
}

@Test
void testCleanupData_withDeleteAllTearDownOperation_executesTearDownOperation()
throws Exception
Expand Down
Loading