- 浏览: 1527052 次
- 性别:
- 来自: 厦门
博客专栏
-
Spring 3.x企业实...
浏览量:464129
文章分类
最新评论
-
JyeChou:
学习Spring必学的Java基础知识(1)----反射 -
hhzhaoheng:
...
《Spring4.x企业应用开发实战》光盘资料下载 -
renlongnian:
//assertReflectionEquals(user1, ...
单元测试系列之3:测试整合之王Unitils -
骑着蜗牛超F1:
huang_yong 写道我的经验是,只需定义三层:1.ent ...
Spring的事务管理难点剖析(2):应用分层的迷惑 -
wangyudong:
工具地址貌似更新了哦https://github.com/Wi ...
几种常用的REST webservice客户端测试工具
抱怨
dbunit这么多人用,这个项目居然好像没有人在维护了,自动2012年9月release一个版本后,再没有更新了,寒心啊。
dbunit有一个大大的BUG,即会解释不了MySQL表的结构,在使用@DataSet准备数据时,会抛出类似如下的异常:
网上有很多痛苦的人在苦苦寻答案,但都依旧痛苦着...
http://zfanxu.iteye.com/blog/1508339
http://bbs.csdn.net/topics/310215234
其实这是dbunit的一个BUG,好像很多版本都有这个问题,报告说解决了,其实并没有解决。我使用最新的2.4.9的版本照样会抛出这个问题。
解决
碰到问题光抱怨是没有用的,又不能指望dbunit的作者改,只能自己着腾了。按照网上的几篇文章改了dbunit的源码,重新编译上传到自己的Maven私服上。终于解决了。
为了避免大家再重新更改编译,我把已经解译好的dbunit jar放在附件中,大家需要的话可以下载使用。
继续...
最近又在整基于DB2的unitils框架,发现又出现问题了,结果再次好好跟踪了unitils及dbunit的源码,终于有了颠覆性的重大发现:
原来网上一直说的是DBUNIT框架导致这个问题的说明是错误的,真正的错误是unitils框架的错误!!
因为DBUNIT已经为不同数据库提供了不同的接口实现:
而unitils(具体地说是DbUnitModule模块)不管你什么数据库,它统一使用这个类:
如果数据库不特殊,当然用DefaultMetadataHandler这个没有问题,如果特殊,则就取不到数据库的Metadata信息了,结果异常就发生了。
但是,目前的DBUnit的Db2MetadataHandler确实是有BUG的,所以我的解决方法是:
1)复写了unitils的DbUnitModule实现类;
2)复写了dbunit的Db2MetadataHandler实现类;
3)配置unitils的配置文件,应用这些自定义的实现类。
下面是MyDb2MetadataHandler的源码:
最后一步,更改unitils.properties的配置:
总结
采用前面的解决方案只能解决mysql的问题,且直接改dbunit的源码,是不好的方案,现在我把它废弃了,大家就不要了。
采用第二种方案吧,是优雅的解决方案,没有更改dbunit的源码,仅通过unitils的扩展配置实现了,所以你不要下载附件的dbunit-2.4.8.2.jar了,直接使用最新的dbunit版本吧:
这个问题啊,让我死几回的心都有了,现在终于解决了,希望对大家有帮助!
dbunit这么多人用,这个项目居然好像没有人在维护了,自动2012年9月release一个版本后,再没有更新了,寒心啊。
dbunit有一个大大的BUG,即会解释不了MySQL表的结构,在使用@DataSet准备数据时,会抛出类似如下的异常:
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) ... 35 more Caused by: org.dbunit.dataset.NoSuchColumnException: t_upload_file.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) ... 37 more
网上有很多痛苦的人在苦苦寻答案,但都依旧痛苦着...
http://zfanxu.iteye.com/blog/1508339
http://bbs.csdn.net/topics/310215234
其实这是dbunit的一个BUG,好像很多版本都有这个问题,报告说解决了,其实并没有解决。我使用最新的2.4.9的版本照样会抛出这个问题。
解决
碰到问题光抱怨是没有用的,又不能指望dbunit的作者改,只能自己着腾了。按照网上的几篇文章改了dbunit的源码,重新编译上传到自己的Maven私服上。终于解决了。
为了避免大家再重新更改编译,我把已经解译好的dbunit jar放在附件中,大家需要的话可以下载使用。
继续...
最近又在整基于DB2的unitils框架,发现又出现问题了,结果再次好好跟踪了unitils及dbunit的源码,终于有了颠覆性的重大发现:
原来网上一直说的是DBUNIT框架导致这个问题的说明是错误的,真正的错误是unitils框架的错误!!
因为DBUNIT已经为不同数据库提供了不同的接口实现:
org.dbunit.database.IMetadataHandler
而unitils(具体地说是DbUnitModule模块)不管你什么数据库,它统一使用这个类:
org.dbunit.database.DefaultMetadataHandler
如果数据库不特殊,当然用DefaultMetadataHandler这个没有问题,如果特殊,则就取不到数据库的Metadata信息了,结果异常就发生了。
但是,目前的DBUnit的Db2MetadataHandler确实是有BUG的,所以我的解决方法是:
1)复写了unitils的DbUnitModule实现类;
2)复写了dbunit的Db2MetadataHandler实现类;
3)配置unitils的配置文件,应用这些自定义的实现类。
package com.ridge.test.unitils.ext; import org.dbunit.database.DatabaseConfig; import org.dbunit.database.DefaultMetadataHandler; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.datatype.IDataTypeFactory; import org.dbunit.dataset.filter.ITableFilterSimple; import org.dbunit.ext.db2.Db2DataTypeFactory; import org.dbunit.ext.db2.Db2MetadataHandler; import org.dbunit.ext.mysql.MySqlDataTypeFactory; import org.dbunit.ext.mysql.MySqlMetadataHandler; import org.unitils.core.UnitilsException; import org.unitils.core.dbsupport.DbSupport; import org.unitils.core.dbsupport.DefaultSQLHandler; import org.unitils.core.dbsupport.SQLHandler; import org.unitils.dbunit.DbUnitModule; import org.unitils.dbunit.util.DbUnitDatabaseConnection; import javax.sql.DataSource; import static org.dbunit.database.DatabaseConfig.FEATURE_BATCHED_STATEMENTS; import static org.dbunit.database.DatabaseConfig.PROPERTY_DATATYPE_FACTORY; import static org.dbunit.database.DatabaseConfig.PROPERTY_ESCAPE_PATTERN; import static org.unitils.core.dbsupport.DbSupportFactory.getDbSupport; import static org.unitils.core.util.ConfigUtils.getInstanceOf; /** * @author : chenxh(quickselect@163.com) * @date: 13-10-9 */ public class MyDbunitModule extends DbUnitModule { protected DbUnitDatabaseConnection createDbUnitConnection(String schemaName) { // A DbSupport instance is fetched in order to get the schema name in correct case DataSource dataSource = getDatabaseModule().getDataSourceAndActivateTransactionIfNeeded(); SQLHandler sqlHandler = new DefaultSQLHandler(dataSource); DbSupport dbSupport = getDbSupport(configuration, sqlHandler, schemaName); // Create connection DbUnitDatabaseConnection connection = new DbUnitDatabaseConnection(dataSource, dbSupport.getSchemaName()); DatabaseConfig config = connection.getConfig(); // Make sure that dbunit's correct IDataTypeFactory, that handles dbms specific data type issues, is used IDataTypeFactory dataTypeFactory = getInstanceOf(IDataTypeFactory.class, configuration, dbSupport.getDatabaseDialect()); config.setProperty(PROPERTY_DATATYPE_FACTORY, dataTypeFactory); // Make sure that table and column names are escaped using the dbms-specific identifier quote string if (dbSupport.getIdentifierQuoteString() != null) config.setProperty(PROPERTY_ESCAPE_PATTERN, dbSupport.getIdentifierQuoteString() + '?' + dbSupport.getIdentifierQuoteString()); // Make sure that batched statements are used to insert the data into the database config.setProperty(FEATURE_BATCHED_STATEMENTS, "true"); // Make sure that Oracle's recycled tables (BIN$) are ignored (value is used to ensure dbunit-2.2 compliancy) config.setProperty("http://www.dbunit.org/features/skipOracleRecycleBinTables", "true"); //注意这儿:根据不同的数据库(unitils的database.dialect配置参数)为dbunit //指定使用不同的IMetadataHandler实现(其它数据库都可以用默认的,还有一个Netezza也是特别的,这里忽略了) if("db2".equalsIgnoreCase(configuration.getProperty("database.dialect"))){ config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Db2DataTypeFactory()); //由于dbunit自身提供的Db2MetadataHandler有BUG,所以这里使用自己写的 //MyDb2MetadataHandler,源码在后面了。 config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MyDb2MetadataHandler()); }else if("mysql".equalsIgnoreCase(configuration.getProperty("database.dialect"))){ config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory()); config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler()); } return connection; } }
下面是MyDb2MetadataHandler的源码:
package com.ridge.test.unitils.ext; import org.dbunit.ext.db2.Db2MetadataHandler; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import org.dbunit.util.SQLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author : chenxh(quickselect@163.com) * @date: 13-10-9 */ public class MyDb2MetadataHandler extends Db2MetadataHandler { private static final Logger logger = LoggerFactory.getLogger(MyDb2MetadataHandler.class); public ResultSet getTables(DatabaseMetaData metaData, String schemaName, String[] tableType) throws SQLException { if(logger.isTraceEnabled()) logger.trace("tableExists(metaData={}, schemaName={}, tableType={}) - start", new Object[] {metaData, schemaName, tableType} ); return metaData.getTables(null, schemaName, "%", tableType); } public boolean tableExists(DatabaseMetaData metaData, String schema, String tableName) throws SQLException { ResultSet tableRs = metaData.getTables(null, schema, tableName, null); try { return tableRs.next(); } finally { SQLHelper.close(tableRs); } } public ResultSet getColumns(DatabaseMetaData databaseMetaData, String schemaName, String tableName) throws SQLException { // Note that MySQL uses the catalogName instead of the schemaName, so // pass in the given schema name as catalog name (first argument). ResultSet resultSet = databaseMetaData.getColumns( null, schemaName, tableName, "%"); return resultSet; } public boolean matches(ResultSet columnsResultSet, String catalog, String schema, String table, String column, boolean caseSensitive) throws SQLException { String catalogName = columnsResultSet.getString(1); String schemaName = columnsResultSet.getString(2); String tableName = columnsResultSet.getString(3); String columnName = columnsResultSet.getString(4); // MYSQL provides only a catalog but no schema if(schema != null && schemaName == null && catalog==null && catalogName != null){ logger.debug("Switching catalog/schema because the are mutually null"); schemaName = catalogName; catalogName = null; } boolean areEqual = areEqualIgnoreNull(table, tableName, caseSensitive) && areEqualIgnoreNull(column, columnName, caseSensitive); return areEqual; } private boolean areEqualIgnoreNull(String value1, String value2, boolean caseSensitive) { return SQLHelper.areEqualIgnoreNull(value1, value2, caseSensitive); } }
最后一步,更改unitils.properties的配置:
... unitils.module.dbunit.className=com.ridge.test.unitils.ext.MyDbunitModule ...
总结
采用前面的解决方案只能解决mysql的问题,且直接改dbunit的源码,是不好的方案,现在我把它废弃了,大家就不要了。
采用第二种方案吧,是优雅的解决方案,没有更改dbunit的源码,仅通过unitils的扩展配置实现了,所以你不要下载附件的dbunit-2.4.8.2.jar了,直接使用最新的dbunit版本吧:
<dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.4.9</version>> </exclusions> </dependency>
这个问题啊,让我死几回的心都有了,现在终于解决了,希望对大家有帮助!
- dbunit-2.4.8.2.jar (586.8 KB)
- 下载次数: 73
发表评论
-
几种常用的REST webservice客户端测试工具
2015-07-30 16:11 9717引言 开发了Rest WebService服务后,如果方便快捷 ... -
关于Idea testng单元测试乱码的解决
2013-07-02 10:50 14165问题 我是使用intel ... -
HyperSQL 2.0
2012-11-01 15:15 1962HyperSQL 2.0于本月7日发布了。此次发布距HSQLD ... -
Mockito
2012-06-07 16:40 7562Overview Packag ... -
追求代码质量: JUnit 4 与 TestNG 的对比
2012-05-05 15:35 2259经过长时间积极的开发之后,JUnit 4.0 于今年年初 ... -
探索 JUnit 4.4 新特性
2012-05-05 14:51 1794摘自:http://www.ibm.com 随着当前 ... -
单元测试系列之5:使用unitils测试Service层
2012-04-14 10:48 18443引述:Spring 的测试框架为我们提供一个强大的测试环境,解 ... -
单元测试系列之4:使用Unitils测试DAO层
2012-04-12 16:32 19683Spring 的测试框架为我们提供一个强大的测试环境,解 ... -
dbunit和poi版本不兼容的问题
2012-04-07 14:59 6960使用unitiles+dbunit 2.4.8,由于我的 ... -
单元测试系列之2:模拟利器Mockito
2012-03-30 11:38 15302引述:程序测试对 ... -
单元测试系列之1:开发测试的那些事儿
2012-03-28 12:52 10013引述:程序测试对保障应用程序正确性而言,其重要性怎 ...
相关推荐
DBUNIT 使用 DbUnit 是一种用于数据库集成测试的重要工具,它提供了TestCase 子类,用户可以在自己的测试类中扩展它们,但也可以独立于 JUnit 以其他方式来使用 DbUnit。DbUnit 的主要用途是准备数据库和验证数据库...
DBUnit 是一个开源的 Java 库,专门用于数据库测试,它是 xUnit 测试框架的一部分,提供了数据驱动测试的解决方案。在版本 2.4.9 中,DBUnit 提供了一系列的功能,帮助开发者在进行单元测试时能够管理和操作数据库的...
DBUnit 是一个开源的 Java 库,专门用于数据库测试,它是 xUnit 测试框架(如 JUnit)的一个扩展。在数据库驱动的项目中,DBUnit 可以帮助开发者确保数据库状态的一致性,使得测试更加可靠。DBUnit 2.4.7 版本包含了...
这篇“DBUnit最佳实践之数据备份与恢复”博文中,作者分享了如何有效地利用DBUnit进行数据备份和恢复,这对于开发和测试环境中的数据管理至关重要。 首先,我们需要了解DBUnit的基本概念。DBUnit是一个JUnit扩展,...
DBUnit 是一个 Java 开发者常用的数据库测试工具,它与JUnit等测试框架配合,能够帮助开发者在测试过程中管理和填充数据库,确保数据的一致性和准确性。本文将深入探讨如何结合Ant构建自动化测试流程,利用DBUnit...
Dbunit 是一个强大的Java库,专门用于数据库的测试和数据管理。它被广泛应用于软件开发过程中,特别是对于那些依赖于数据库的应用程序,因为Dbunit能够帮助开发者有效地管理和控制数据库的状态,确保测试的一致性...
总之,DBUnit帮助文档(HTML版)为开发者提供了一站式的数据库测试解决方案,无论是初学者还是经验丰富的测试人员,都能从中受益。通过深入学习和实践,你可以更有效地管理和维护数据库状态,确保测试的质量和可靠性。
DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类...
DBUnit 是一个 Java 平台上的数据库测试工具,它提供了数据驱动测试的框架,使得开发者能够在测试用例中填充、清理或验证数据库状态。在本文中,我们将深入探讨 DBUnit 的最佳实践,聚焦于数据库的增删改查操作,...
DBUnit 是一个开源的Java库,它扩展了JUnit框架,为数据库相关的单元测试提供了一种结构化的方法。在“dbunit2.2”这个压缩包中,包含了DBUnit 2.2版本的所有必要文件,使得开发者能够有效地进行数据库的单元测试。 ...
2. **junit.jar**:JUnit 是一个流行的单元测试框架,DBUnit 常常与之配合使用,提供对数据库层的测试支持。它提供了断言、测试套件和测试监听器等机制,使得编写和运行测试变得简单。 3. **commons-dbcp.jar** 或 ...
DbUnit 入门实战 DbUnit 是一个专门针对数据库测试的 JUnit 扩展,它可以将测试对象数据库置于一个测试轮回之间的状态。...同时,DbUnit 也可以与其他测试框架集成,提供更加全面的测试解决方案。
6. 清理:如果需要,使用`DatabaseOperation.CLEAN_INSERT`之类的操作清理数据库,以便于下一次测试。 对于开发团队而言,使用DBUnit 可以提高测试覆盖率,减少因数据库问题导致的bug,同时也能简化回归测试过程,...
DBUnit 是一个 Java 编程语言的开源工具,专门用于数据库的单元测试。它与JUnit 结合使用,提供了一种结构化的方法来设置和验证数据库的状态,确保代码的正确性。在进行数据库驱动的应用程序开发时,DBUnit 可以帮助...
DBUnit 是一个开源的 Java 库,专门用于数据库测试,它是 xUnit 测试框架(如 JUnit)的一个扩展。在数据库驱动的项目中,DBUnit 提供了一种结构化的方法来设置和验证数据库状态,从而确保测试的一致性和可靠性。这...
DBUnit 是一个开源的 Java 库,专门用于数据库测试,它是 xUnit 测试框架(如 JUnit)的一个扩展。在软件开发中,确保数据库状态的一致性...结合 JUnit 或其他测试框架,DBUnit 能帮助你构建强大的数据库测试解决方案。
dbunit的jar包,版本2.2
DBUNIT 是一个开源的 Java 库,专门用于数据库测试,它提供了一种结构化的方法来设置和验证数据库的状态。在软件开发中,测试是保证代码质量和功能正确性的重要环节,而 DBUNIT 尤其适用于对数据库操作进行测试,...
**IDatabaseConnection** 是DbUnit的核心接口之一,它代表了一个到数据库的连接。DbUnit提供了两种实现方式:`DatabaseConnection` 包装了JDBC连接,而 `DatabaseDataSourceConnection` 则包装了JDBC的数据源。这两...