name.didier.david.test4j.dbunit.DbUnitTestSupport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ndd-test4j Show documentation
Show all versions of ndd-test4j Show documentation
Test4J provides testing support.
The newest version!
package name.didier.david.test4j.dbunit;
import static java.util.Arrays.stream;
import static name.didier.david.check4j.ConciseCheckers.checkNotNull;
import javax.sql.DataSource;
import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.DefaultPrepAndExpectedTestCase;
import org.dbunit.IDatabaseTester;
import org.dbunit.PrepAndExpectedTestCase;
import org.dbunit.PrepAndExpectedTestCaseSteps;
import org.dbunit.VerifyTableDefinition;
import org.dbunit.util.fileloader.DataFileLoader;
import org.dbunit.util.fileloader.FlatXmlDataFileLoader;
/**
* Support class dealing with database testing with DbUnit.
*
* @author ddidier
*/
public class DbUnitTestSupport {
/** The {@link DataSource} used to connect to the database. */
private final DataSource dataSource;
/** The DbUnit test case. */
private final PrepAndExpectedTestCase testCase;
/**
* @param dataSource the {@link DataSource} used to connect to the database.
*/
public DbUnitTestSupport(DataSource dataSource) {
this.dataSource = checkNotNull(dataSource, "dataSource");
this.testCase = createTestCase();
}
/**
* @return the {@link DataSource} used to connect to the database.
*/
public DataSource getDataSource() {
return dataSource;
}
/**
* Seed the data, run the test then check the data. See {@link PrepAndExpectedTestCase}.
*
* @param seedDataPaths the paths of the data files to load as seed data.
* @param expectedDataPaths the paths of the data files to load as expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
* @return a user defined object from running the test steps.
*/
public Object test(
String[] seedDataPaths,
String[] expectedDataPaths,
VerifyTableDefinition[] verifiedTables,
TestStepsWithResult testSteps) {
return doTest(seedDataPaths, expectedDataPaths, verifiedTables,
(PrepAndExpectedTestCaseSteps) () -> testSteps.run());
}
/**
* Seed the data, run the test then check the data. This is a convenience method when there is not need for
* testSteps
to return a value. See {@link PrepAndExpectedTestCase}.
*
* @param seedDataPaths the paths of the data files to load as seed data.
* @param expectedDataPaths the paths of the data files to load as expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
*/
public void test(
String[] seedDataPaths,
String[] expectedDataPaths,
VerifyTableDefinition[] verifiedTables,
TestStepsWithoutResult testSteps) {
doTest(seedDataPaths, expectedDataPaths, verifiedTables, (PrepAndExpectedTestCaseSteps) () -> {
testSteps.run();
return null;
});
}
/**
* Seed the data, run the read-only test then check the data. See {@link PrepAndExpectedTestCase}.
*
* @param seedDataPaths the paths of the data files to load as seed data and expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
* @return a user defined object from running the test steps.
*/
public Object testReadOnly(
String[] seedDataPaths,
VerifyTableDefinition[] verifiedTables,
TestStepsWithResult testSteps) {
return test(seedDataPaths, seedDataPaths, verifiedTables, testSteps);
}
/**
* Seed the data, run the read-only test then check the data. This is a convenience method when there is not need
* for testSteps
to return a value. See {@link PrepAndExpectedTestCase}.
*
* @param seedDataPaths the paths of the data files to load as seed data and expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
*/
public void testReadOnly(
String[] seedDataPaths,
VerifyTableDefinition[] verifiedTables,
TestStepsWithoutResult testSteps) {
test(seedDataPaths, seedDataPaths, verifiedTables, testSteps);
}
/**
* Defines database tables to verify (assert on data), including all columns.
*
* @param tableNames the names of the tables to verify.
* @return database tables to verify
*/
public static VerifyTableDefinition[] verifyTables(String... tableNames) {
return stream(tableNames)
.map(name -> new VerifyTableDefinition(name, new String[0]))
.toArray(VerifyTableDefinition[]::new);
}
/**
* @return a new test case using a {@link DataSourceDatabaseTester} and a {@link FlatXmlDataFileLoader}.
*/
protected PrepAndExpectedTestCase createTestCase() {
IDatabaseTester dbTester = new DataSourceDatabaseTester(dataSource);
DataFileLoader loader = new FlatXmlDataFileLoader();
return new DefaultPrepAndExpectedTestCaseExtension(loader, dbTester);
}
/**
* Seed the data, run the test then check the data.
*
* @param seedDataPaths the paths of the data files to load as seed data.
* @param expectedDataPaths the paths of the data files to load as expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
* @return a user defined object from running the test steps.
*/
protected Object doTest(
String[] seedDataPaths,
String[] expectedDataPaths,
VerifyTableDefinition[] verifiedTables,
PrepAndExpectedTestCaseSteps testSteps) {
try {
return testCase.runTest(verifiedTables, seedDataPaths, expectedDataPaths, testSteps);
} catch (AssertionError e) {
throw e;
} catch (Throwable e) {
// OK to catch Throwable here (for assertions)
throw new RuntimeException("Error while testing database state", e);
}
}
// -----------------------------------------------------------------------------------------------------------------
/**
* Test steps definition without returned value (void). Helpful for Java lambdas.
*
* @author ddidier
*/
@FunctionalInterface
public interface TestStepsWithoutResult {
/**
* Run the specific test steps.
*
* @throws Exception if an error occurs.
*/
void run()
throws Exception;
}
/**
* Test steps definition with returned value. Helpful for Java lambdas.
*
* @author ddidier
*/
@FunctionalInterface
public interface TestStepsWithResult {
/**
* Run the specific test steps.
*
* @return a user specific object.
* @throws Exception if an error occurs.
*/
Object run()
throws Exception;
}
/**
* Do not swallow {@link AssertionError}s raised in the test steps.
*
* @author ddidier
*/
public static class DefaultPrepAndExpectedTestCaseExtension
extends DefaultPrepAndExpectedTestCase {
/**
* @param dataFileLoader load the data files.
* @param databaseTester manipulate database.
*/
public DefaultPrepAndExpectedTestCaseExtension(DataFileLoader dataFileLoader, IDatabaseTester databaseTester) {
super(dataFileLoader, databaseTester);
}
/**
* Seed the data, run the test then check the data. Do not swallow raised {@link AssertionError}s.
*
* @param seedDataPaths the paths of the data files to load as seed data.
* @param expectedDataPaths the paths of the data files to load as expected data.
* @param verifiedTables the table definitions to verify after test execution.
* @param testSteps the test steps to run.
* @return a user defined object from running the test steps.
*/
@Override
public Object runTest(
VerifyTableDefinition[] verifiedTables,
String[] seedDataPaths,
String[] expectedDataPaths,
PrepAndExpectedTestCaseSteps testSteps)
throws Exception {
Throwable throwable = null;
try {
preTest(verifiedTables, seedDataPaths, expectedDataPaths);
return testSteps.run();
} catch (final Throwable t) {
// OK to catch Throwable here (for assertions)
throwable = t;
throw t;
} finally {
// do not test expected data if an exception was raised
// since the comparison itself may raise an exception
// which will hide the former one
postTest(throwable == null);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy