diff --git a/src/main/java/org/dbunit/DefaultPrepAndExpectedTestCase.java b/src/main/java/org/dbunit/DefaultPrepAndExpectedTestCase.java
index 8ec4913a7..16fb69502 100644
--- a/src/main/java/org/dbunit/DefaultPrepAndExpectedTestCase.java
+++ b/src/main/java/org/dbunit/DefaultPrepAndExpectedTestCase.java
@@ -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;
@@ -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.
+ *
+ * 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.
*
* @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"
@@ -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. */
@@ -1067,6 +1091,11 @@ private void logSortedTable(final String tableTypeName,
/**
* Compare the tables, enables easy overriding.
+ *
+ * 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.
@@ -1081,9 +1110,17 @@ protected void compareData(final ITable expectedTable,
final Map 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);
+ }
}
/**
@@ -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
diff --git a/src/test/java/org/dbunit/DefaultPrepAndExpectedTestCaseTest.java b/src/test/java/org/dbunit/DefaultPrepAndExpectedTestCaseTest.java
index 431bd65e9..0f10054e4 100644
--- a/src/test/java/org/dbunit/DefaultPrepAndExpectedTestCaseTest.java
+++ b/src/test/java/org/dbunit/DefaultPrepAndExpectedTestCaseTest.java
@@ -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;
@@ -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