使用Dbunit+Unitils出现 org.dbunit.dataset.NoSuchColumnException 的解决方法

最近使用dbunit-2.4.8 + Unitils 3.3做DAO层数据库测试的时候

出现如下错误:

org.unitils.core.UnitilsException: Error inserting test data from DbUnit dataset for method public void org.zfanxu.test.UserDaoTestWithUnitils.testGetUserById()
	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:49)
	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: user.ID -  (Non-uppercase input column: 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:140)
	at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
	at org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy.doExecute(CleanInsertLoadStrategy.java:45)
	at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:44)
	... 20 more

于是在网上google下得知是dbunit的一个bug:http://stackoverflow.com/questions/2210429/dbunit-confusion-over-case-sensitivity-on-table-column-names

google上也基本没有可行的解决方案!

后来我通过修改dbunit的源代码得以解决,错误的原因是unitils默认使用的是“DefaultMetadataHandler.java”这个类去加载数据库信息,从而得不到数据库schema的值

扫描二维码关注公众号,回复: 712366 查看本文章

    DefaultMetadataHandler.java

boolean areEqual = 
                areEqualIgnoreNull(catalog, catalogName, caseSensitive) &&
                areEqualIgnoreNull(schema, schemaName, caseSensitive) &&
                areEqualIgnoreNull(table, tableName, caseSensitive) &&
                areEqualIgnoreNull(column, columnName, caseSensitive);

 这个时候的schemaName是空的,但是传进来的schema是有值的,从而报错!

所以解决方法如下:

方法1. 修改DefaultMetadataHandler.java文件将上述代码换成如下代码

boolean areEqual = 
                areEqualIgnoreNull(table, tableName, caseSensitive) &&
                areEqualIgnoreNull(column, columnName, caseSensitive);

   对,我把catalog和schema的比较都删掉了!

方法2: 因为我使用的是mysql数据库,我直接把dbunit中的类"MySqlMetadataHandler"覆盖掉原来的DefaultMetadataHandler.java文件,同样能解决问题

最后,也来个抛砖引玉,如果有人有更好的解决方法或是可以不通过修改源代码解决的,可以回复我! :-D

猜你喜欢

转载自zfanxu.iteye.com/blog/1508339