【讓開發自動化】Unitils與DBUnit 兼容性問題

因爲系統裏用到了POI-3.5.FINAL用於Excel的處理,而unitils配套的DBUnit才2.2版本,與POI-3.5版本衝突,須要升級DBUnit的版本。目測最新版爲2.4.9,與POI-3.5正好配套,一運行,出現以下異常: java

org.unitils.core.UnitilsException: Error inserting test data from DbUnit dataset for method public void com.litt.cidp.system.service.OperatorServiceTest.test_load()
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:156)
	at org.unitils.dbunit.DbUnitModule$DbUnitListener.beforeTestSetUp(DbUnitModule.java:557)
	at org.unitils.core.Unitils$UnitilsTestListener.beforeTestSetUp(Unitils.java:273)
	at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runBeforesThenTestThenAfters(UnitilsJUnit4TestClassRunner.java:151)
	at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
	at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
	at org.unitils.UnitilsJUnit4TestClassRunner.invokeTestMethod(UnitilsJUnit4TestClassRunner.java:95)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
	at org.unitils.UnitilsJUnit4TestClassRunner.access$000(UnitilsJUnit4TestClassRunner.java:44)
	at org.unitils.UnitilsJUnit4TestClassRunner$1.run(UnitilsJUnit4TestClassRunner.java:62)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
	at org.unitils.UnitilsJUnit4TestClassRunner.run(UnitilsJUnit4TestClassRunner.java:68)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.unitils.core.UnitilsException: Error while executing DataSetLoadStrategy
	at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:46)
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:230)
	at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:153)
	... 18 more
Caused by: org.dbunit.dataset.NoSuchColumnException: operator.OP_ID -  (Non-uppercase input column: OP_ID) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
	at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)
	at org.dbunit.operation.AbstractOperation.getOperationMetaData(AbstractOperation.java:89)
	at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:143)
	at org.unitils.dbunit.datasetloadstrategy.impl.InsertLoadStrategy.doExecute(InsertLoadStrategy.java:45)
	at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:44)
	... 20 more

中間過程就不贅述了,直接看問題根源org.dbunit.database.DatabaseTableMetaData。其內部 Column[] _columns未被正確初始化 ,致使最終dbunit數據操做失敗。跟蹤代碼能夠看到是metadataHandler.matches出了問題,在進一步跟蹤咱們能夠看到,這個方法傳入了ResultSet和schemaName用於對象識別,然而從ResultSet中得到的schemaName爲空,匹配識別,致使Column獲取失敗。 數組

public Column[] getColumns() throws DataSetException
    {
        logger.debug("getColumns() - start");

        if (_columns == null)    //這裏得到的是一個長度爲0的數組,不爲空
        {
...

            List columnList = new ArrayList();
            while (resultSet.next())
            {
                // Check for exact table/schema name match because
                // databaseMetaData.getColumns() uses patterns for the lookup
                
                //這裏的match沒有匹配到
                boolean match = metadataHandler.matches(resultSet, schemaName, tableName, _caseSensitiveMetaData);
                if(match)
                {
                    Column column = SQLHelper.createColumn(resultSet, dataTypeFactory, datatypeWarning);
                    if(column != null)
                    {
                        columnList.add(column);
                    }
                 }
                 else
                 {
                       logger.debug("Skipping <schema.table> '" + resultSet.getString(2) + "." + 
                              resultSet.getString(3) + "' because names do not exactly match.");
                  }
              }


              if (columnList.size() == 0)
              {
                   logger.warn("No columns found for table '"+ tableName +"' that are supported by dbunit. " +"Will return an empty column list");
                    }
public boolean matches(ResultSet columnsResultSet, String catalog,
            String schema, String table, String column,
            boolean caseSensitive) throws SQLException 
    {
        if(logger.isTraceEnabled())
            logger.trace("matches(columnsResultSet={}, catalog={}, schema={}," +
            		" table={}, column={}, caseSensitive={}) - start", 
                    new Object[] {columnsResultSet, catalog, schema, 
                            table, column, Boolean.valueOf(caseSensitive)});
        
        String catalogName = columnsResultSet.getString(1);
        String schemaName = columnsResultSet.getString(2);  //這裏得到的schemaName爲空
        String tableName = columnsResultSet.getString(3);
        String columnName = columnsResultSet.getString(4);

        if(logger.isDebugEnabled()){
            logger.debug("Comparing the following values using caseSensitive={} (searched<=>actual): " +
                    "catalog: {}<=>{} schema: {}<=>{} table: {}<=>{} column: {}<=>{}", 
                    new Object[] {
                        Boolean.valueOf(caseSensitive),
                        catalog, catalogName,
                        schema, schemaName,
                        table, tableName,
                        column, columnName
                    });
        }
        
        boolean areEqual = 
                areEqualIgnoreNull(catalog, catalogName, caseSensitive) &&
                areEqualIgnoreNull(schema, schemaName, caseSensitive) &&
                areEqualIgnoreNull(table, tableName, caseSensitive) &&
                areEqualIgnoreNull(column, columnName, caseSensitive);
        return areEqual;
    }

經進一步覈實,DBUnit新版本中的處理方式與老版本不一樣,老版本中使用了SQLHelper並處理了MySql,schema的問題,新版本中須要指定metadataHandler的實現類,而Unitils因爲配套的僅爲2.2版本,暫不支持該配置方式。
eclipse

解決方案: spa

  • 將dbunit降級到2.4.2版本;
  • 或修改unitils的源碼;

BUG追蹤:https://unitils.atlassian.net/browse/UNI-152 .net

相關文章
相關標籤/搜索