DbUnitAssert.java

  1. /*
  2.  *
  3.  * The DbUnit Database Testing Framework
  4.  * Copyright (C)2002-2008, DbUnit.org
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  *
  20.  */
  21. package org.dbunit.assertion;

  22. import java.sql.SQLException;

  23. import org.dbunit.DatabaseUnitException;
  24. import org.dbunit.assertion.comparer.value.ValueComparers;
  25. import org.dbunit.database.IDatabaseConnection;
  26. import org.dbunit.dataset.Column;
  27. import org.dbunit.dataset.IDataSet;
  28. import org.dbunit.dataset.ITable;
  29. import org.dbunit.dataset.datatype.DataType;
  30. import org.dbunit.dataset.datatype.UnknownDataType;
  31. import org.dbunit.dataset.filter.DefaultColumnFilter;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;

  34. /**
  35.  * Default implementation of DbUnit assertions, based on the original methods
  36.  * present at {@link org.dbunit.Assertion}.
  37.  *
  38.  * All are equality comparisons.
  39.  *
  40.  * @author Felipe Leme (dbunit@felipeal.net)
  41.  * @author gommma (gommma AT users.sourceforge.net)
  42.  * @version $Revision$ $Date$
  43.  * @since 2.4.0
  44.  */
  45. public class DbUnitAssert extends DbUnitAssertBase
  46. {
  47.     private static final Logger logger =
  48.             LoggerFactory.getLogger(DbUnitAssert.class);

  49.     /**
  50.      * Compare one table present in two datasets ignoring specified columns.
  51.      *
  52.      * @param expectedDataset
  53.      *            First dataset.
  54.      * @param actualDataset
  55.      *            Second dataset.
  56.      * @param tableName
  57.      *            Table name of the table to be compared.
  58.      * @param ignoreCols
  59.      *            Columns to be ignored in comparison.
  60.      * @throws org.dbunit.DatabaseUnitException
  61.      *             If an error occurs.
  62.      */
  63.     public void assertEqualsIgnoreCols(final IDataSet expectedDataset,
  64.             final IDataSet actualDataset, final String tableName,
  65.             final String[] ignoreCols) throws DatabaseUnitException
  66.     {
  67.         logger.debug(
  68.                 "assertEqualsIgnoreCols(expectedDataset={}, actualDataset={}, tableName={}, ignoreCols={}) - start",
  69.                 expectedDataset, actualDataset, tableName, ignoreCols);

  70.         assertEqualsIgnoreCols(expectedDataset.getTable(tableName),
  71.                 actualDataset.getTable(tableName), ignoreCols);
  72.     }

  73.     /**
  74.      * Compare the given tables ignoring specified columns.
  75.      *
  76.      * @param expectedTable
  77.      *            First table.
  78.      * @param actualTable
  79.      *            Second table.
  80.      * @param ignoreCols
  81.      *            Columns to be ignored in comparison.
  82.      * @throws org.dbunit.DatabaseUnitException
  83.      *             If an error occurs.
  84.      */
  85.     public void assertEqualsIgnoreCols(final ITable expectedTable,
  86.             final ITable actualTable, final String[] ignoreCols)
  87.             throws DatabaseUnitException
  88.     {
  89.         logger.debug(
  90.                 "assertEqualsIgnoreCols(expectedTable={}, actualTable={}, ignoreCols={}) - start",
  91.                 expectedTable, actualTable, ignoreCols);

  92.         final ITable expectedTableFiltered = DefaultColumnFilter
  93.                 .excludedColumnsTable(expectedTable, ignoreCols);
  94.         final ITable actualTableFiltered = DefaultColumnFilter
  95.                 .excludedColumnsTable(actualTable, ignoreCols);
  96.         assertEquals(expectedTableFiltered, actualTableFiltered);
  97.     }

  98.     /**
  99.      * Compare a table from a dataset with a table generated from an sql query.
  100.      *
  101.      * @param expectedDataset
  102.      *            Dataset to retrieve the first table from.
  103.      * @param connection
  104.      *            Connection to use for the SQL statement.
  105.      * @param sqlQuery
  106.      *            SQL query that will build the data in returned second table
  107.      *            rows.
  108.      * @param tableName
  109.      *            Table name of the table to compare.
  110.      * @param ignoreCols
  111.      *            Columns to be ignored in comparison.
  112.      * @throws DatabaseUnitException
  113.      *             If an error occurs while performing the comparison.
  114.      * @throws java.sql.SQLException
  115.      *             If an SQL error occurs.
  116.      */
  117.     public void assertEqualsByQuery(final IDataSet expectedDataset,
  118.             final IDatabaseConnection connection, final String sqlQuery,
  119.             final String tableName, final String[] ignoreCols)
  120.             throws DatabaseUnitException, SQLException
  121.     {
  122.         logger.debug(
  123.                 "assertEqualsByQuery(expectedDataset={}, connection={}, tableName={}, sqlQuery={}, ignoreCols={}) - start",
  124.                 expectedDataset, connection, tableName, sqlQuery, ignoreCols);

  125.         final ITable expectedTable = expectedDataset.getTable(tableName);
  126.         assertEqualsByQuery(expectedTable, connection, tableName, sqlQuery,
  127.                 ignoreCols);
  128.     }

  129.     /**
  130.      * Compare a table with a table generated from an sql query.
  131.      *
  132.      * @param expectedTable
  133.      *            Table containing all expected results.
  134.      * @param connection
  135.      *            Connection to use for the SQL statement.
  136.      * @param tableName
  137.      *            The name of the table to query from the database.
  138.      * @param sqlQuery
  139.      *            SQL query that will build the data in returned second table
  140.      *            rows.
  141.      * @param ignoreCols
  142.      *            Columns to be ignored in comparison.
  143.      * @throws DatabaseUnitException
  144.      *             If an error occurs while performing the comparison.
  145.      * @throws java.sql.SQLException
  146.      *             If an SQL error occurs.
  147.      */
  148.     public void assertEqualsByQuery(final ITable expectedTable,
  149.             final IDatabaseConnection connection, final String tableName,
  150.             final String sqlQuery, final String[] ignoreCols)
  151.             throws DatabaseUnitException, SQLException
  152.     {
  153.         logger.debug(
  154.                 "assertEqualsByQuery(expectedTable={}, connection={}, tableName={}, sqlQuery={}, ignoreCols={}) - start",
  155.                 expectedTable, connection, tableName, sqlQuery, ignoreCols);

  156.         final ITable expected = DefaultColumnFilter
  157.                 .excludedColumnsTable(expectedTable, ignoreCols);
  158.         final ITable queriedTable =
  159.                 connection.createQueryTable(tableName, sqlQuery);
  160.         final ITable actual = DefaultColumnFilter
  161.                 .excludedColumnsTable(queriedTable, ignoreCols);
  162.         assertEquals(expected, actual);
  163.     }

  164.     /**
  165.      * Asserts that the two specified dataset are equals. This method ignore the
  166.      * tables order.
  167.      */
  168.     public void assertEquals(final IDataSet expectedDataSet,
  169.             final IDataSet actualDataSet) throws DatabaseUnitException
  170.     {
  171.         logger.debug(
  172.                 "assertEquals(expectedDataSet={}, actualDataSet={}) - start",
  173.                 expectedDataSet, actualDataSet);
  174.         assertEquals(expectedDataSet, actualDataSet, null);
  175.     }

  176.     /**
  177.      * Asserts that the two specified dataset are equals. This method ignore the
  178.      * tables order.
  179.      *
  180.      * @since 2.4
  181.      */
  182.     public void assertEquals(final IDataSet expectedDataSet,
  183.             final IDataSet actualDataSet, final FailureHandler failureHandler)
  184.             throws DatabaseUnitException
  185.     {
  186.         assertWithValueComparer(expectedDataSet, actualDataSet, failureHandler,
  187.                 null, null);
  188.     }

  189.     protected void compareTables(final IDataSet expectedDataSet,
  190.             final IDataSet actualDataSet, final String[] expectedNames,
  191.             final FailureHandler failureHandler) throws DatabaseUnitException
  192.     {
  193.         compareTables(expectedDataSet, actualDataSet, expectedNames,
  194.                 failureHandler, null, null);
  195.     }

  196.     /**
  197.      * Asserts that the two specified tables are equals. This method ignores the
  198.      * table names, the columns order, the columns data type and which columns
  199.      * are composing the primary keys.
  200.      *
  201.      * @param expectedTable
  202.      *            Table containing all expected results.
  203.      * @param actualTable
  204.      *            Table containing all actual results.
  205.      * @throws DatabaseUnitException
  206.      */
  207.     public void assertEquals(final ITable expectedTable,
  208.             final ITable actualTable) throws DatabaseUnitException
  209.     {
  210.         logger.debug("assertEquals(expectedTable={}, actualTable={}) - start",
  211.                 expectedTable, actualTable);
  212.         assertEquals(expectedTable, actualTable, (Column[]) null);
  213.     }

  214.     /**
  215.      * Asserts that the two specified tables are equals. This method ignores the
  216.      * table names, the columns order, the columns data type and which columns
  217.      * are composing the primary keys. <br />
  218.      * Example: <code><pre>
  219.      * ITable actualTable = ...;
  220.      * ITable expectedTable = ...;
  221.      * ITableMetaData metaData = actualTable.getTableMetaData();
  222.      * Column[] additionalInfoCols = Columns.getColumns(new String[] {"MY_PK_COLUMN"}, metaData.getColumns());
  223.      * assertEquals(expectedTable, actualTable, additionalInfoCols);
  224.      * </pre></code>
  225.      *
  226.      * @param expectedTable
  227.      *            Table containing all expected results.
  228.      * @param actualTable
  229.      *            Table containing all actual results.
  230.      * @param additionalColumnInfo
  231.      *            The columns to be printed out if the assert fails because of a
  232.      *            data mismatch. Provides some additional column values that may
  233.      *            be useful to quickly identify the columns for which the
  234.      *            mismatch occurred (for example a primary key column). Can be
  235.      *            <code>null</code>.
  236.      * @throws DatabaseUnitException
  237.      */
  238.     public void assertEquals(final ITable expectedTable,
  239.             final ITable actualTable, final Column[] additionalColumnInfo)
  240.             throws DatabaseUnitException
  241.     {
  242.         logger.debug(
  243.                 "assertEquals(expectedTable={}, actualTable={}, additionalColumnInfo={}) - start",
  244.                 expectedTable, actualTable, additionalColumnInfo);

  245.         FailureHandler failureHandler = null;
  246.         if (additionalColumnInfo != null)
  247.         {
  248.             failureHandler = getDefaultFailureHandler(additionalColumnInfo);
  249.         }

  250.         assertEquals(expectedTable, actualTable, failureHandler);
  251.     }

  252.     /**
  253.      * Asserts that the two specified tables are equals. This method ignores the
  254.      * table names, the columns order, the columns data type and which columns
  255.      * are composing the primary keys. <br />
  256.      * Example: <code><pre>
  257.      * ITable actualTable = ...;
  258.      * ITable expectedTable = ...;
  259.      * ITableMetaData metaData = actualTable.getTableMetaData();
  260.      * FailureHandler failureHandler = new DefaultFailureHandler();
  261.      * assertEquals(expectedTable, actualTable, failureHandler);
  262.      * </pre></code>
  263.      *
  264.      * @param expectedTable
  265.      *            Table containing all expected results.
  266.      * @param actualTable
  267.      *            Table containing all actual results.
  268.      * @param failureHandler
  269.      *            The failure handler used if the assert fails because of a data
  270.      *            mismatch. Provides some additional information that may be
  271.      *            useful to quickly identify the rows for which the mismatch
  272.      *            occurred (for example by printing an additional primary key
  273.      *            column). Can be <code>null</code>.
  274.      * @throws DatabaseUnitException
  275.      * @since 2.4
  276.      */
  277.     public void assertEquals(final ITable expectedTable,
  278.             final ITable actualTable, final FailureHandler failureHandler)
  279.             throws DatabaseUnitException
  280.     {
  281.         assertWithValueComparer(expectedTable, actualTable, failureHandler,
  282.                 ValueComparers.isActualEqualToExpectedWithEmptyFailMessage,
  283.                 null);
  284.     }

  285.     /**
  286.      * Represents a single column to be used for the comparison of table data.
  287.      * It contains the {@link DataType} to be used for comparing the given
  288.      * column. This {@link DataType} matches the expected and actual column's
  289.      * datatype.
  290.      *
  291.      * @author gommma (gommma AT users.sourceforge.net)
  292.      * @author Last changed by: $Author: gommma $
  293.      * @version $Revision: 864 $ $Date: 2008-11-07 06:27:26 -0800 (Fri, 07 Nov
  294.      *          2008) $
  295.      * @since 2.4.0
  296.      */
  297.     public static class ComparisonColumn
  298.     {
  299.         private static final Logger logger =
  300.                 LoggerFactory.getLogger(ComparisonColumn.class);

  301.         private String columnName;
  302.         private DataType dataType;

  303.         /**
  304.          * @param tableName
  305.          *            The table name which is only needed for debugging output.
  306.          * @param expectedColumn
  307.          *            The expected column needed to resolve the {@link DataType}
  308.          *            to use for the actual comparison.
  309.          * @param actualColumn
  310.          *            The actual column needed to resolve the {@link DataType}
  311.          *            to use for the actual comparison.
  312.          * @param failureHandler
  313.          *            The {@link FailureHandler} to be used when no datatype can
  314.          *            be determined.
  315.          */
  316.         public ComparisonColumn(final String tableName,
  317.                 final Column expectedColumn, final Column actualColumn,
  318.                 final FailureHandler failureHandler)
  319.         {
  320.             this.columnName = expectedColumn.getColumnName();
  321.             this.dataType = getComparisonDataType(tableName, expectedColumn,
  322.                     actualColumn, failureHandler);
  323.         }

  324.         /**
  325.          * @return The column actually being compared.
  326.          */
  327.         public String getColumnName()
  328.         {
  329.             return this.columnName;
  330.         }

  331.         /**
  332.          * @return The {@link DataType} to use for the actual comparison.
  333.          */
  334.         public DataType getDataType()
  335.         {
  336.             return this.dataType;
  337.         }

  338.         /**
  339.          * @param tableName
  340.          *            The table name which is only needed for debugging output.
  341.          * @param expectedColumn
  342.          * @param actualColumn
  343.          * @param failureHandler
  344.          *            The {@link FailureHandler} to be used when no datatype can
  345.          *            be determined.
  346.          * @return The dbunit {@link DataType} to use for comparing the given
  347.          *         column.
  348.          */
  349.         private DataType getComparisonDataType(final String tableName,
  350.                 final Column expectedColumn, final Column actualColumn,
  351.                 final FailureHandler failureHandler)
  352.         {
  353.             logger.debug(
  354.                     "getComparisonDataType(tableName={}, expectedColumn={}, actualColumn={}, failureHandler={}) - start",
  355.                     tableName, expectedColumn, actualColumn, failureHandler);

  356.             final DataType expectedDataType = expectedColumn.getDataType();
  357.             final DataType actualDataType = actualColumn.getDataType();

  358.             // The two columns have different data type
  359.             if (!expectedDataType.getClass().isInstance(actualDataType))
  360.             {
  361.                 // Expected column data type is unknown, use actual column data
  362.                 // type
  363.                 if (expectedDataType instanceof UnknownDataType)
  364.                 {
  365.                     return actualDataType;
  366.                 }

  367.                 // Actual column data type is unknown, use expected column data
  368.                 // type
  369.                 if (actualDataType instanceof UnknownDataType)
  370.                 {
  371.                     return expectedDataType;
  372.                 }

  373.                 // Impossible to determine which data type to use
  374.                 final String msg = "Incompatible data types: (table="
  375.                         + tableName + ", col=" + expectedColumn.getColumnName()
  376.                         + ")";
  377.                 throw failureHandler.createFailure(msg,
  378.                         String.valueOf(expectedDataType),
  379.                         String.valueOf(actualDataType));
  380.             }

  381.             // Both columns have same data type, return any one of them
  382.             return expectedDataType;
  383.         }
  384.     }
  385. }