Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using DbUnit with tables which do not have primary keys

Tags:

java

junit

dbunit

I'm attempting to set up my unit testing environment to use DbUnit.

I'm having a few problems as the tables which I am attempting to control do not have primary keys. I have been getting a org.dbunit.dataset.NoPrimaryKeyException.

I have followed the steps here http://dbunit.wikidot.com/noprimarykeytable but how do I use:

connection.getConfig().setProperty("http://www.dbunit.org/properties/primaryKeyFilter", new MyPrimaryKeyFilter("A1"));

for each of my tables?

For example, I have the following database:

CREATE TABLE `NO_PK1` (
  `A1` int(11) NOT NULL,
  `A2` varchar(50) default NULL
);

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <NO_PK1 A1="1" A2="Test1" />
  <NO_PK1 A1="2" A2="Test2" />
  <NO_PK1 A1="3" />
</dataset>

CREATE TABLE `NO_PK2` (
  `B1` int(11) NOT NULL,
  `B2` varchar(50) default NULL
);

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <NO_PK2 B1="1" B2="Test1" />
  <NO_PK2 B1="2" B2="Test2" />
  <NO_PK2 B1="3" />
</dataset>

CREATE TABLE `NO_PK3` (
  `C1` int(11) NOT NULL,
  `C2` varchar(50) default NULL
);

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <NO_PK3 C1="1" C2="Test1" />
  <NO_PK3 C1="2" C2="Test2" />
  <NO_PK3 C1="3" />
</dataset>

How do I rewrite connection.getConfig().setProperty("http://www.dbunit.org/properties/primaryKeyFilter", new MyPrimaryKeyFilter("A1")); in this instance?

Many thanks for any advice.

like image 580
mip Avatar asked Feb 03 '12 15:02

mip


2 Answers

You need to make sure that your MyPrimaryKeyFilter handles all the tables in your schema. In the example, there is only one table, so the simple filter class provided works fine. In your case, I would probably change that class to take a Map containing table -> pk column name mappings:

class MyPrimaryKeyFilter implements IColumnFilter {
        private Map<String, String> pseudoKey = null;

        MyPrimaryKeyFilter(Map<String, String> pseudoKey) {
            this.pseudoKey = pseudoKey;
        }

        public boolean accept(String tableName, Column column) {
            return column.getColumnName().equalsIgnoreCase(pseudoKey.get(tableName));
        }

    }

and then set up the map with {NO_PK1 -> A1}, {NO_PK2 -> B1}, and {NO_PK3 -> C1} entries.

like image 120
slushi Avatar answered Oct 22 '22 08:10

slushi


I fall into same issue and found solution in these blogs:

  • http://www.expertaya.com/2011/04/20/dbunit-composite-primary-keys/
  • http://blog.eflow.org/archives/65
  • http://www.baselogic.com/blog/development/test-driven-development/dbunit-unable-import-data-collectiontable-witout-primary-key/

All blog's authors start from http://dbunit.wikidot.com/noprimarykeytable

This code shown different strategies for checking id:

public static IDatabaseConnection getConnection(DataSource ds) throws Exception {
    Connection con = ds.getConnection();
    final DatabaseMetaData dbMetaData = con.getMetaData();
    DatabaseConnection dbUnitCon = new DatabaseConnection(con, dbMetaData.getUserName().toUpperCase());
    DatabaseConfig dbUnitConfig = dbUnitCon.getConfig();
    dbUnitConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Oracle10DataTypeFactory());
    dbUnitConfig.setProperty(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, Boolean.TRUE);
    dbUnitConfig.setProperty(DatabaseConfig.PROPERTY_PRIMARY_KEY_FILTER, new IColumnFilter() {

        Map<String, List<String>> tablePrimaryKeyMap = new HashMap<>();
        {
            tablePrimaryKeyMap.put("CLIENT", Arrays.asList(new String[]{"FIRST_NAME", "MIDDLE_NAME", "LAST_NAME"}));
            // ...
        }

        @Override
        public boolean accept(String tableName, Column column) {
            if ((tableName.startsWith("DATA_") || tableName.startsWith("PAYMENT_"))
                    && ("COMPANY".equalsIgnoreCase(tableName) || "FILIAL".equalsIgnoreCase(tableName)
                        || "BRANCH".equalsIgnoreCase(tableName) || "CASTOMER".equalsIgnoreCase(tableName)
                        || "XDATE".equalsIgnoreCase(tableName)))
                return true;
            if (tablePrimaryKeyMap.containsKey(tableName))
                return tablePrimaryKeyMap.get(tableName).contains(column.getColumnName());
            else if ("id".equalsIgnoreCase(column.getColumnName())) {
                return true;
            }
            try {
                ResultSet rs = dbMetaData.getPrimaryKeys(null, null, tableName);
                while (rs.next()) {
                    rs.getString("COLUMN_NAME");
                    if (rs.getString("COLUMN_NAME").equalsIgnoreCase(column.getColumnName())) {
                        return true;
                    }
                }
            } catch (SQLException ex) {
                Logger.getLogger(DistributionControllerDbTest.class.getName()).log(Level.SEVERE, null, ex);
            }
            return false;
        }
    });
    return dbUnitCon;
}
like image 4
gavenkoa Avatar answered Oct 22 '22 10:10

gavenkoa