`

让Unitils实现excel下的多数据源支持

    博客分类:
  • Test
阅读更多
说明:这里的多数据源需要利用spring中配置的多个DataSource.而且仅针对oracle数据库. 在oracle有一个schema的概念, 一个datasource下可能有多个schema, 而一个schema一般会跟一组用户名密码绑定, 这里我们采用用户名作为schema名称.
为了实现对多schema的支持, unitils提供了一个MultiSchemaXmlDataSetFactory, 也就是在采用xml的格式来实现多数据源的创建, 但不知道为什么原因, 没有提供对excel格式的多schema的支持, 而对于所有测试都采用excel来构造测试数据用户来说, 则显得有些无奈, 为了实现这个功能, 了解了一下unitils-dbunit, dbunit相关的源代码, 不过有些困难, 一个是dbunit提供的接口对我们的扩展有一些限制. 比如我们希望我们在excel中定义测试数据的时候, 每个sheet的名称将采用"datasourceName.tablename"的约定来定义. 因此我们必须在解析excel文件的时候, 必须从中已有的table中解析出datasource和tablename.
废话少说, 其具体做法是: 在从excel中取得DataSet之后(一个excel对应一个DataSet, 一个Sheet对应一个Table), 将DataSet中的所有Table根据datasource名称进行重组, 然后将得到的多个DataSet用MultiSchemaDataSet进行封装. 而MultiSchemaXlsDataSetFactory类的工作就是为了创建这个MultiSchemaDataSet.
/**
* 需要在unitils.properties文件中将<tt>DbUnitModule.DataSet.factory.default</tt>属性名设置为该类全限定名.
* 
 * @author lengda
 * @since 2009-12-3 下午04:15:29
 */
public class MultiSchemaXlsDataSetFactory implements DataSetFactory {
    private static Pattern pattern = Pattern.compile("\\.");
    protected String defaultSchemaName;

    public void init(Properties configuration, String defaultSchemaName) {
        this.defaultSchemaName = defaultSchemaName;
    }

    public MultiSchemaDataSet createDataSet(File... dataSetFiles) {
        Map<String, List<ITable>> tableMap = getTables(dataSetFiles);

        MultiSchemaDataSet dataSets = new MultiSchemaDataSet();
        for (Entry<String, List<ITable>> entry : tableMap.entrySet()) {
            List<ITable> tables = entry.getValue();
            try {
                DefaultDataSet ds = new DefaultDataSet(tables.toArray(new ITable[] {}));
                dataSets.setDataSetForSchema(entry.getKey(), ds);
            } catch (AmbiguousTableNameException e) {
                throw new UnitilsException(String.format("使用指定表[%s]重新构造DataSet失败", tables), e);
            }
        }

        return dataSets;
    }

    private Map<String, List<ITable>> getTables(File... dataSetFiles) {
        Map<String, List<ITable>> tableMap = new HashMap<String, List<ITable>>();
        // 需要根据schema把Table重新组合一下
        try {
            for (File file : dataSetFiles) {
                IDataSet dataSet = new XlsDataSet(new FileInputStream(file));
                String[] tableNames = dataSet.getTableNames();
                for (String each : tableNames) {
                    // 这个实际上不是schema, 是对应的spring的datasouceId
                    String schema = null;
                    String tableName;
                    String[] temp = pattern.split(each);
                    if (temp.length == 2) {
                        schema = temp[0];
                        tableName = temp[1];
                    } else {
                        schema = this.defaultSchemaName;
                        tableName = each;
                    }

                    ITable table = dataSet.getTable(each);
                    if (!tableMap.containsKey(schema)) {
                        tableMap.put(schema, new ArrayList<ITable>());
                    }
                    tableMap.get(schema).add(new XslTableWrapper(tableName, table));
                }
            }
        } catch (Exception e) {
            throw new UnitilsException("Unable to create DbUnit dataset for data set files: "
                    + Arrays.toString(dataSetFiles), e);
        }
        return tableMap;
    }

    public String getDataSetFileExtension() {
        return "xls";
    }

}


为了对XslTable重新进行封装, 使用了下面的类来处理去掉datasource后的tablename, 因为在执行过程中ITableMetaData会使用到表名, 而这个表名我们是没办法通过继承来进行修改的, 只能通过代理的形式了.
/**
* 为了获得strip datasource后的表名
* 
 * @author lengda
 * @since 2009-12-3 下午06:44:36
 */
class XslTableWrapper extends AbstractTable {
    private ITable delegate;
    private String tableName;

    public XslTableWrapper(String tableName, ITable table) {
        this.delegate = table;
        this.tableName = tableName;
    }
    public int getRowCount() {
        return delegate.getRowCount();
    }

    public ITableMetaData getTableMetaData() {
        ITableMetaData meta = delegate.getTableMetaData();
        try {
            return new DefaultTableMetaData(tableName, meta.getColumns(), meta.getPrimaryKeys());
        } catch (DataSetException e) {
            throw new UnitilsException("Don't get the meta info from  " + meta, e);
        }
    }

    public Object getValue(int row, String column) throws DataSetException {
        Object delta = delegate.getValue(row, column);
        if (delta instanceof String) {
            if (StringUtils.isEmpty((String) delta)) {
                return null;
            }
        }
        return delta;
    }

}


另外目前本人使用的unitls版本为3.1, 而在其内部依赖的dbunit版本为2.2.2, 这个版本使用解析excel的poi版本在处理excel中cell的格式为日期的时候, 会有问题, 需要指定一下dbunit的最新版本2.4.6, 在maven中的依赖配置:
        <dependency>
          <groupId>org.unitils</groupId>
          <artifactId>unitils-dbunit</artifactId>
          <version>${unitils.version}</version>
          <exclusions>
            <exclusion>
                <groupId>org.dbunit</groupId>
                <artifactId>dbunit</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.1-FINAL</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.4.6</version>
            <scope>compile</scope>
        </dependency>

分享到:
评论
3 楼 kkeli 2012-06-11  
zfanxu 写道
请问,为什么我在MYSQL数据库下,运行的你的代码,程序不报错,但是数据也没插入到数据库中?

晕了,dbunit本来就是为了不破坏数据库现场才使用的测试工具,测试结束后就回滚了
2 楼 mojunbin 2012-05-10  
"StringUtils"这个类是org.apache.commons.lang.StringUtils否?
1 楼 zfanxu 2012-05-03  
请问,为什么我在MYSQL数据库下,运行的你的代码,程序不报错,但是数据也没插入到数据库中?

相关推荐

    unitils整合dbunit利用excel进行单元测试

    unitils整合dbunit利用excel进行单元测试 包含mock以及整合spring进行测试

    Unitils单元测试

    Unitils的模块化设计是其另一大特点,包括unitils-core(核心模块)、unitils-database(数据库管理)、unitils-DbUnit(DbUnit集成)、unitils-easymock(EasyMock支持)、unitils-inject(对象注入)、unitils-...

    Unitils示例

    在 Unitils 中,EasyMock 提供了对方法调用的模拟,可以模拟方法的返回值、抛出异常等,从而在不依赖实际实现的情况下测试代码逻辑。这有助于编写更简洁、独立的单元测试。 4. **项目结构** - `pom.xml`: Maven 的...

    Unitils教程(介绍Unitils的最佳资料)

    Unitils 提供了一些实用的断言方法,让我们可以轻松地验证测试结果。 在上面的例子中,我们使用 assertEquals 方法来比较两个 User 对象是否相等。然而,断言失败,因为 User 类没有覆写 equals() 方法。为了避免...

    Unitils-jar包

    Unitils 测试框架目的是让单元测试变得更加容易和可维护。Unitils 构建在DbUnit 与 EasyMock 项目之上并与JUnit 和TestNG 相结合。支持数据库测试,支持利用Mock 对象 进行测试并提供与Spring 和Hibernate 相集成。...

    使用Unitils测试DAO

    Unitils是一个自动化测试框架,它提供了对Spring、Hibernate等流行技术的内置支持,让开发者能够快速编写可维护的测试代码。它包含了一些模块,如数据库测试、ORM测试和依赖注入测试,旨在减少设置和清理测试环境所...

    Unitils-core-3.3.jar

    Unitils-core-3.3的jar包

    unitils-2.2

    在深入探讨Unitils的功能之前,让我们先理解一下单元测试和集成测试的重要性。 单元测试是软件开发中的关键环节,它允许开发者对代码的各个独立部分进行验证,确保每个模块都能正确工作。这有助于早期发现和修复...

    unitils-3.3-with-dependencies.zip

    "Unitils-3.3-with-dependencies.zip" 是一个包含Unitils 3.3版本及其所有依赖库的压缩包文件。Unitils是一个流行的Java开发框架,专注于自动化单元测试和集成测试。这个压缩包包含了运行和使用Unitils所需的所有...

    Integrete unitils for database(dao) testing

    让我们深入探讨一下Unitils库以及它在数据库测试中的应用。 Unitils是一个开源的Java测试框架,它提供了丰富的功能,帮助开发者简化单元测试和集成测试。在数据库测试方面,Unitils提供了自动化管理数据库和数据的...

    基于mybatis高级映射多对多查询的实现

    在MyBatis中,处理多对多关系查询是一项常见的任务,尤其在数据模型设计中,很多情况下两个实体之间存在多对多的关系。本篇将详细解释如何使用MyBatis的高级映射来实现多对多查询。 首先,我们来看一个实际场景:...

    对dbunit进行mybatis DAO层Excel单元测试(必看篇)

    接着,使用dbunit来进行单元测试,可以使用Excel文件作为测试数据源。 六、结论 本文围绕对dbunit进行mybatis DAO层Excel单元测试,介绍了相关的知识点和实现方法。Dbunit是一个功能强大且易于使用的数据库单元...

    Unitils框架与模块扩展

    Unitils框架与模块扩展Unitils这个Java开源包的目的是让单元测试变得更加容易和维护。Unitils构建在DBUnit与EasyMock项目之上并与JUnit和TestNG相结合,支持数据库测试,支持利用mock对象进行测试并提供与Spring和...

    spock-unitils-0.7-groovy-2.0.zip

    Unitils则是一个专注于简化单元测试的Java库,它提供了诸如数据库和持久层支持等功能。Groovy是Java平台上的动态语言,与Java代码可互操作,其语法简洁,易于编写。 描述中的 "bytesize.zip" 提到了一个用于处理...

    Unitil学习

    此外,Unitils还支持数据库测试,这意味着开发者可以在不依赖实际数据库环境的情况下,测试与数据库交互的代码段。它允许创建测试专用的数据库配置,执行测试中的SQL脚本,以及在测试结束时清理测试数据。这样的能力...

    改资源配准测试

    例如,可能需要重新定义数据源配置,以提高数据库访问的并发性能;或者调整Unitils的数据清理策略,确保测试数据的隔离性;甚至可能需要定制化DBUtils的一些操作,以满足特定的数据库交互需求。 在实际操作中,`...

    junit单元测试jar包集

    它支持多种数据格式(如XML或CSV),使得测试数据的管理更加方便。通过DBUnit,开发者可以确保数据库操作不影响其他测试,提高了测试的隔离性。 **Unitils** 是一个集成了多种测试辅助功能的框架,`unitils-3.3-...

    unitils-selenium:使用 Selenium 测试 Web 应用程序的 Unitils 模块-开源

    Unitils 模块 - 启动 Selenium Web 驱动程序以测试 Web 应用程序的简单方法。

    Spring.3.x企业应用开发实战(完整版).part2

    8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础知识 9.1.1 何为数据库事务 9.1.2 数据并发的问题 9.1.3 数据库锁机制 9.1.4 事务隔离级别 9.1.5 JDBC对事务支持 9.2 ThreadLocal...

Global site tag (gtag.js) - Google Analytics