每次用开源的框架时,最蛋疼的不是业务逻辑如何如何复杂,而是痛苦的版本问题。开源的框架都不是不同的团队搞出来的东西,因此版本兼容做的不是很全面完善。可是作为一个小程序员也没有必要去指责框架的问题了,毕竟我们自己造轮子还是太费时,还有最重要的是水平达不到啊。在此就先发发牢骚了,下面切入正题了,相信用过unitils的朋友们都遇到过这个问题喽,截图如下:(此为dbunit2.4.9和poi3.9最新版本)
java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFDateUtil.isCellDateFormatted(Lorg/apache/poi/hssf/usermodel/HSSFCell;)Z at org.dbunit.dataset.excel.XlsTable.getValue(XlsTable.java:153) at unitils.test.excel.MultiSchemaXlsDataSetReader$XlsTable.getValue(MultiSchemaXlsDataSetReader.java:114) at org.dbunit.operation.AbstractBatchOperation.isEmpty(AbstractBatchOperation.java:77) at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:135) 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) at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:230) at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:153) 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:86) 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:33) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45) 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)
这里总是提示NoSuchMethod这个问题,翻看dbunit的pom.xml文件发现他依赖的是poi3.2-FINAL版本,这个真是让人吐血啊,这个版本比较久了,虽然在spring中导出Excel视图我用的是poi3.9版本,这两个版本Cell的创建方式不同,但我还是为了解决它换了poi3.2-FINAL版本,期望问题得以解决。在满怀信心的点击了
Junit Test后我的心凉了,发现又会提示如下错误:
org.unitils.core.UnitilsException: Error inserting test data from DbUnit dataset for method public void unitils.test.impl.UserDaoTest.findUserByUserName() 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:86) 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:33) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45) 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: 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
细看Caused by:是没有这列user.ID,google,度娘后发现只能是改源码或者把dbunit换成2.4.2版本。确实dbunit2.4.2和poi3.2-FINAL可以完美兼容,问题得以解决。可是我不甘心啊,为什么辛辛苦苦写的spring Excel View却要因为一个测试要从新更改为poi3.2的API,这是个不小的工程。于是我选择了暴力的手段,更改源码,google上说其实dbunit可以支持高版本的poi,就是要改pom文件,然后重新编译。
在网上找到了dbunit2.4.9的源码包,更改poi的依赖改为如下:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> <exclusions> <exclusion> <artifactId>log4j</artifactId> <groupId>log4j</groupId> </exclusion> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> <optional>true</optional> </dependency>
这样源码再重新编译时用到的就是poi3.9的API了,dbunit就可以支持高版本的poi版本了。
第一个问题得已解决了,第二个问题找不到***.ID是由于unitils和dbunit的版本不兼容的问题,因为unitils支持的dbunit是2.2.2。而unitils默认调用的是dbunit的DefaultMetadataHandler.class,需要把这个类更改为如下:
boolean areEqual = areEqualIgnoreNull(table, tableName, caseSensitive) && areEqualIgnoreNull(column, columnName, caseSensitive); return areEqual;
这样第二个问题得以解决了,当然也得重新编译dbunit2.4.9喽,最后问题得以解决了。截图如下:
下面我就献上我重新编译好的dbunit2.4.9jar文件和它的源码包,想自己编译就编译下好了,想用的就下载jar文件了。在此在说一句,在如此浩瀚的开源框架中何时才是个头啊,什么时候能用上自己的框架啊,哈哈哈。。。