All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jmockring.utils.dbunit.DbUnitRule Maven / Gradle / Ivy

The newest version!
package org.jmockring.utils.dbunit;

import static org.jmockring.utils.dbunit.PropertyUtil.configurePlaceholders;
import static org.jmockring.utils.dbunit.PropertyUtil.getProperty;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.dbunit.IDatabaseTester;
import org.dbunit.IOperationListener;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.CompositeDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.CompositeOperation;
import org.dbunit.operation.DatabaseOperation;
import org.dbunit.operation.DeleteAllOperation;
import org.dbunit.operation.InsertOperation;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JUnit rule to manage the DBUnit setup/tear down operations.
 * Inclusion of this rule in the test is the only requirement to make DBUnit facility work.
 * 

* Example: *

 *  ....
 *
 * {@literal @}Rule
 *  public DbUnitRule dbUnitRule = new DbUnitRule("/dbunit/dbunit.properties",
 *      "dbunit/entity1_dataset.xml",
 *      "dbunit/entity2_dataset.xml",
 *      "dbunit/entity3_dataset.xml"
 *  ).withTuner(DbUnitTuner.H2);
 *
 *  ....
 * 
*

* Expects the following properties in order to set up the DB connection: *

  • dbunit.driver
  • *
  • dbunit.connectionUrl
  • *
  • dbunit.user
  • *
  • dbunit.password
  • *

    * These can be provided via {@link Properties} or via a filename of a classpath relative `*.properties` resource *

    * IMPORTANT: *

    * Rules can be used in test suites, however bear in mind that when test is executed outside the suite these rules will not apply. * This may require temporarily copying the suite rule inside the test, while debugging. * * @author Pavel Lechev * @since 05/06/13 */ public class DbUnitRule extends ExternalResource implements IOperationListener { private static final Logger log = LoggerFactory.getLogger(DbUnitRule.class); private String[] dataSetFileNames; private IDatabaseTester databaseTester; private boolean debugOnExit; private CompositeDataSet loadedDataSet; private DbUnitPostExecutor postExecutor; private DatabaseOperation setupOperation = DatabaseOperation.CLEAN_INSERT; private DatabaseOperation tearDownOperation = DatabaseOperation.DELETE_ALL; private DbUnitTuner tuner; /** * See {@link #DbUnitRule(Properties, String...)} * * @param propertiesFileName * @param dataSetFileNames */ public DbUnitRule(String propertiesFileName, String... dataSetFileNames) { Properties properties = new Properties(); try { String fileName = configurePlaceholders(propertiesFileName); properties.load(DbUnitRule.class.getResourceAsStream((fileName.startsWith("/") ? "" : "/") + fileName)); } catch (IOException e) { throw new IllegalArgumentException(e); } init(properties, dataSetFileNames); } /** * Constructs a rule with: *

    * - DBUnit setUpOperation = CLEAN_INSERT
    * - DBUnit tearDownOperation = DELETE_ALL
    * * @param properties * @param dataSetFileNames */ public DbUnitRule(Properties properties, String... dataSetFileNames) { init(properties, dataSetFileNames); } @Override public void connectionRetrieved(IDatabaseConnection connection) { // log.debug("[DB UNIT] connectionRetrieved called //"); if (this.tuner != null) { // log.debug("[DB UNIT] calling the tuner"); this.tuner.tune(connection); } } /** * Call this to cause dump of some debug info on exit. * * @return * @see #debug(Connection) */ public DbUnitRule debugOnExit() { this.debugOnExit = true; return this; } @Override public void operationSetUpFinished(IDatabaseConnection connection) { // log.debug("[DB UNIT] operationSetUpFinished called"); closeConnection(connection); } @Override public void operationTearDownFinished(IDatabaseConnection connection) { // log.debug("[DB UNIT] operationTearDownFinished called"); closeConnection(connection); if (this.postExecutor != null) { this.postExecutor.execute(connection); } } /** * Test classes can get hold of the DB Unit tester and register * themselves as listeners or perform other setup operations. * * @return */ public IDatabaseTester getDatabaseTester() { return databaseTester; } /** * @param postExecutor * @return */ public DbUnitRule withPostExecutor(DbUnitPostExecutor postExecutor) { this.postExecutor = postExecutor; return this; } public DbUnitRule withSetupOperation(DatabaseOperation setupOperation) { this.setupOperation = setupOperation; return this; } /** * Typically the default tear down operation should be used, but when debugging failing tests * it is sometimes useful to preserve the data in the database for verification, etc ... *

    * In this case we can temporary set up custom tear down operation ({@link DatabaseOperation#NONE}). *

    * Example usage: *

         *  ....
         *
         * {@literal @}Rule
         *  public DbUnitRule dbUnitRule = new DbUnitRule("/dbunit/dbunit.properties",
         *      "dbunit/entity1_dataset.xml",
         *      "dbunit/entity2_dataset.xml",
         *      "dbunit/entity3_dataset.xml"
         *      )
         *      .withTuner(DbUnitTuner.ORACLE)
         *      .withTearDownOperation(DatabaseOperation.NONE);
         *
         *  ....
         * 
    *

    * IMPORTANT: *

    * After this facility is used, make sure you run the changed test * with the default tearDown operation at least once to ensure the test cleans up. * Failure to do so may cause foreign key violations in other tests which * happen to skip some of the affected tables from their XML dataset configurations. * * @param tearDownOperation * @return */ public DbUnitRule withTearDownOperation(DatabaseOperation tearDownOperation) { this.tearDownOperation = tearDownOperation; return this; } /** * Add an optional tuner to be executed after DBUnit obtains the connection. * * @param tuner * @return */ public DbUnitRule withTuner(DbUnitTuner tuner) { this.tuner = tuner; return this; } @Override protected void before() throws Throwable { loadedDataSet = new CompositeDataSet(buildDataSets(dataSetFileNames)); databaseTester.setDataSet(loadedDataSet); databaseTester.onSetup(); } @Override protected void after() { try { if (debugOnExit) { debug(databaseTester.getConnection().getConnection()); } databaseTester.onTearDown(); } catch (Exception e) { throw new IllegalStateException(e); } } /** * @param connection * @throws SQLException * @see #debugOnExit */ private void debug(final Connection connection) throws SQLException { ResultSet rs = connection.getMetaData().getTables(null, null, null, new String[]{"TABLE", "VIEW"}); final StringBuilder sb = new StringBuilder(); while (rs.next()) { final String tableName = rs.getString("TABLE_NAME"); sb.append("\n" + tableName); final ResultSet rr = connection.createStatement().executeQuery("SHOW COLUMNS FROM " + tableName); while (rr.next()) { sb.append("\n\t" + rr.getString(1) + " | " + rr.getString(2)); } } System.out.println(sb); } /** * @param dataSetFileNames * @return * @throws DataSetException */ private IDataSet[] buildDataSets(String[] dataSetFileNames) throws DataSetException { IDataSet[] dataSets = new IDataSet[dataSetFileNames.length]; int i = 0; FlatXmlDataSetBuilder flatXmlDataSetBuilder = new FlatXmlDataSetBuilder(); flatXmlDataSetBuilder.setColumnSensing(true); for (String fileName : dataSetFileNames) { dataSets[i++] = flatXmlDataSetBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName)); } return dataSets; } private void closeConnection(IDatabaseConnection connection) { // log.debug("closeConnection(connection={}) - start", connection); try { connection.close(); } catch (SQLException e) { log.warn("Exception while closing the connection: " + e, e); } } /** * @param properties * @param dataSetFileNames */ private void init(Properties properties, String... dataSetFileNames) { this.dataSetFileNames = dataSetFileNames; try { this.databaseTester = new JdbcDatabaseTester( getProperty(properties, "dbunit.driver"), getProperty(properties, "dbunit.connectionUrl"), getProperty(properties, "dbunit.user"), getProperty(properties, "dbunit.password") ) { /** * * @return * @see CompositeOperation * @see DeleteAllOperation * @see InsertOperation */ @Override protected DatabaseOperation getSetUpOperation() { return setupOperation; } /** * * @return * @see DeleteAllOperation */ @Override protected DatabaseOperation getTearDownOperation() { return tearDownOperation; } }; } catch (ClassNotFoundException e) { throw new IllegalStateException(e); } this.databaseTester.setOperationListener(this); } }





    © 2015 - 2025 Weber Informatics LLC | Privacy Policy