dbunit使用

在本周TDD课程的运行中,我认为编写一些夹具以简化dbUnit的使用将很有趣。 我最初的想法只是教dbUnit有关JSON的知识,但事实证明Lieven Doclo已经做到了。 因此,我决定更进一步,还将dbUnit与JUnit Rules结合起来,并提供HSQLDB内存中对象存储的自动引导。

以下测试显示了我最终得到的结果:

package com.danhaywood.tdd.dbunit.test;import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;import java.sql.ResultSet;
import java.sql.Statement;import org.dbunit.Assertion;
import org.dbunit.dataset.ITable;
import org.hsqldb.jdbcDriver;
import org.junit.Rule;
import org.junit.Test;import com.danhaywood.tdd.dbunit.DbUnitRule;
import com.danhaywood.tdd.dbunit.DbUnitRule.Ddl;
import com.danhaywood.tdd.dbunit.DbUnitRule.JsonData;public class DbUnitRuleExample {@Rulepublic DbUnitRule dbUnit = new DbUnitRule(DbUnitRuleExample.class, jdbcDriver.class,"jdbc:hsqldb:file:src/test/resources/testdb", "SA", "");@Ddl("customer.ddl")@JsonData("customer.json")@Testpublic void update_lastName() throws Exception {// whenStatement statement = dbUnit.getConnection().createStatement();statement.executeUpdate("update customer set last_name='Bloggs' where id=2");// then (verify directly)ResultSet rs2 = dbUnit.executeQuery("select last_name from customer where id = 2");assertThat(rs2.next(), is(true));assertThat(rs2.getString("last_name"), equalTo("Bloggs"));// then (verify using datasets)ITable actualTable = dbUnit.createQueryTable("customer", "select * from customer order by id");ITable expectedTable = dbUnit.jsonDataSet("customer-updated.json").getTable("customer");Assertion.assertEquals(expectedTable, actualTable);}
}

其中customer.ddl是:

drop table customer if exists;
create table customer (id         int         not null primary key,first_name varchar(30) not null,initial    varchar(1)  null,last_name  varchar(30) not null
)

customer.json (初始数据集)为:

{"customer":[{"id": 1,"first_name": "John","initial": "K","last_name": "Smith"},{"id": 2,"first_name": "Mary","last_name": "Jones"}]
}

customer-updated.json (最终数据集)为:

{"customer":[{"id": 1,"first_name": "John","initial": "K","last_name": "Smith"},{"id": 2,"first_name": "Mary","last_name": "Bloggs"}]
}

您可能已经发现, @ Ddl注释可以选择指定要针对数据库运行的DDL脚本,而@JsonData定义了JSON格式的数据集。

DbUnitRule类的实际实现是:

package com.danhaywood.tdd.dbunit;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;import com.google.common.io.Resources;public class DbUnitRule implements MethodRule {@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.METHOD })public static @interface Ddl {String[] value();}@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.METHOD })public static @interface JsonData {String value();}private final Class<?> resourceBase;private IDatabaseTester databaseTester;private IDatabaseConnection dbUnitConnection;private Connection connection;private java.sql.Statement statement;public DbUnitRule(Class<?> resourceBase, Class<?> driver, String url, String user, String password) {this.resourceBase = resourceBase;try {databaseTester = new JdbcDatabaseTester(driver.getName(), url, user, password);dbUnitConnection = databaseTester.getConnection();connection = dbUnitConnection.getConnection();statement = connection.createStatement();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic Statement apply(final Statement base, final FrameworkMethod method, final Object target) {return new Statement() {@Overridepublic void evaluate() throws Throwable {try {Ddl ddl = method.getAnnotation(Ddl.class);if (ddl != null) {String[] values = ddl.value();for (String value : values) {executeUpdate(Resources.toString(resourceBase.getResource(value), Charset.defaultCharset()));}}JsonData data = method.getAnnotation(JsonData.class);if (data != null) {IDataSet ds = new JSONDataSet(resourceBase.getResourceAsStream(data.value()));databaseTester.setDataSet(ds);}databaseTester.onSetup();base.evaluate();} finally {databaseTester.onTearDown();}}};}public java.sql.Connection getConnection() {return connection;}public void executeUpdate(String sql) throws SQLException {statement.executeUpdate(sql);}public ResultSet executeQuery(String sql) throws SQLException {return statement.executeQuery(sql);}public IDataSet jsonDataSet(String datasetResource) {return new JSONDataSet(resourceBase.getResourceAsStream(datasetResource));}public ITable createQueryTable(String string, String string2) throws DataSetException, SQLException {return dbUnitConnection.createQueryTable(string, string2);}
}

这使用了Lieven Doclo的JSONDataSet(为方便起见在此处复制):

import org.codehaus.jackson.map.ObjectMapper;import org.dbunit.dataset.*;
import org.dbunit.dataset.datatype.DataType;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;/*** DBUnit DataSet format for JSON based datasets. It is similar to the flat XML layout,* but has some improvements (columns are calculated by parsing the entire dataset, not just* the first row). It uses Jackson, a fast JSON processor.* <br/><br/>* The format looks like this:* <br/>* <pre>* {*    "&lt;table_name&gt;": [*        {*             "&lt;column&gt;":&lt;value&gt;,*             ...*        },*        ...*    ],*    ...* }* </pre>* <br/>* I.e.:* <br/>* <pre>* {*    "test_table": [*        {*             "id":1,*             "code":"JSON dataset",*        },*        {*             "id":2,*             "code":"Another row",*        }*    ],*    "another_table": [*        {*             "id":1,*             "description":"Foo",*        },*        {*             "id":2,*             "description":"Bar",*        }*    ],*    ...* }* </pre>** @author Lieven DOCLO*/
public class JSONDataSet extends AbstractDataSet {// The parser for the dataset JSON fileprivate JSONITableParser tableParser = new JSONITableParser();// The tables after parsingprivate List<ITable> tables;/*** Creates a JSON dataset based on a file* @param file A JSON dataset file*/public JSONDataSet(File file) {tables = tableParser.getTables(file);}/*** Creates a JSON dataset based on an inputstream* @param is An inputstream pointing to a JSON dataset*/public JSONDataSet(InputStream is) {tables = tableParser.getTables(is);}@Overrideprotected ITableIterator createIterator(boolean reverse) throws DataSetException {return new DefaultTableIterator(tables.toArray(new ITable[tables.size()]));}private class JSONITableParser {private ObjectMapper mapper = new ObjectMapper();/*** Parses a JSON dataset file and returns the list of DBUnit tables contained in* that file* @param jsonFile A JSON dataset file* @return A list of DBUnit tables*/public List<ITable> getTables(File jsonFile) {try {return getTables(new FileInputStream(jsonFile));} catch (IOException e) {throw new RuntimeException(e.getMessage(), e);}}/*** Parses a JSON dataset input stream and returns the list of DBUnit tables contained in* that input stream* @param jsonStream A JSON dataset input stream* @return A list of DBUnit tables*/@SuppressWarnings("unchecked")public List<ITable> getTables(InputStream jsonStream) {List<ITable> tables = new ArrayList<ITable>();try {// get the base object tree from the JSON streamMap<String, Object> dataset = mapper.readValue(jsonStream, Map.class);// iterate over the tables in the object treefor (Map.Entry<String, Object> entry : dataset.entrySet()) {// get the rows for the tableList<Map<String, Object>> rows = (List<Map<String, Object>>) entry.getValue();ITableMetaData meta = getMetaData(entry.getKey(), rows);// create a table based on the metadataDefaultTable table = new DefaultTable(meta);int rowIndex = 0;// iterate through the rows and fill the tablefor (Map<String, Object> row : rows) {fillRow(table, row, rowIndex++);}// add the table to the list of DBUnit tablestables.add(table);}} catch (IOException e) {throw new RuntimeException(e.getMessage(), e);}return tables;}/*** Gets the table meta data based on the rows for a table* @param tableName The name of the table* @param rows The rows of the table* @return The table metadata for the table*/private ITableMetaData getMetaData(String tableName, List<Map<String, Object>> rows) {Set<String> columns = new LinkedHashSet<String>();// iterate through the dataset and add the column names to a setfor (Map<String, Object> row : rows) {for (Map.Entry<String, Object> column : row.entrySet()) {columns.add(column.getKey());}}List<Column> list = new ArrayList<Column>(columns.size());// create a list of DBUnit columns based on the column name setfor (String s : columns) {list.add(new Column(s, DataType.UNKNOWN));}return new DefaultTableMetaData(tableName, list.toArray(new Column[list.size()]));}/*** Fill a table row* @param table The table to be filled* @param row A map containing the column values* @param rowIndex The index of the row to te filled*/private void fillRow(DefaultTable table, Map<String, Object> row, int rowIndex) {try {table.addRow();// set the column values for the current rowfor (Map.Entry<String, Object> column : row.entrySet()) {table.setValue(rowIndex, column.getKey(), column.getValue());}} catch (Exception e) {throw new RuntimeException(e.getMessage(), e);}}}
}

我用于此的库(即依赖项)是:

  • hsqldb 2.2.6
  • dbunit 2.4.8
  • 杰克逊1.9.3
  • slf4j-api-1.6.4,slf4j-nop-1.6.4
  • 谷歌番石榴10.0.1
  • junit 4.8

一如既往,欢迎发表评论。

参考:来自Dan Haywood博客的 JCG合作伙伴 Dan Haywood的dbUnit,JSON,HSQLDB和JUnit Rules的DB单元测试 。

相关文章 :

  • JUnit 4.9(测试版3)中的规则
  • Spring 3使用JUnit 4进行测试– ContextConfiguration和AbstractTransactionalJUnit4SpringContextTests
  • Java RESTful API集成测试
  • 何时用集成测试替换单元测试
  • 我的测试和代码分析工具箱

翻译自: https://www.javacodegeeks.com/2012/01/db-unit-testing-with-dbunit-json-hsqldb.html

dbunit使用

dbunit使用_使用dbUnit,JSON,HSQLDB和JUnit规则进行数据库单元测试相关推荐

  1. 使用dbUnit,JSON,HSQLDB和JUnit规则进行数据库单元测试

    在本周TDD课程的运行中,我认为编写一些夹具以简化dbUnit的使用将很有趣. 我最初的想法只是教dbUnit有关JSON的知识,但事实证明Lieven Doclo已经做到了. 因此,我决定更进一步, ...

  2. junit动态忽略测试_有条件忽略测试的JUnit规则

    junit动态忽略测试 我一直认为使用@Ignore停用测试是一个坏主意. 例外,这可能是一种将间歇性失败的测试放入隔离区以供以后处理的方法(如Martin Fowler 在此处所述 ). 随着越来越 ...

  3. java后台解析json并保存到数据库_[Java教程]ajax 发送json 后台接收 遍历保存进数据库...

    [Java教程]ajax 发送json 后台接收 遍历保存进数据库 0 2017-09-25 15:00:23 前台怎么拿参数的我就不管了我也不会 反正用这个ajax没错 ajax 代码   一定要写 ...

  4. Node.js 官网入门教程(二) npm(安装、包版本、卸载、npx)、package.json(scripts、devDependencies)package-lock.json(语义版本规则符号

    Node.js 官网入门教程(二) npm(包管理.安装.包版本.卸载.npx).package.json(scripts.devDependencies).package-lock.json(语义版 ...

  5. Python3进阶--正则表达式、json、logging日志配置、数据库操作、枚举、闭包、匿名函数和高阶函数、time、datetime

    第一章 变量.常用循环体.代码结构.代码练习 第二章 列表.元组等数据结构.字符串驻留机制及字符串格式化操作 第三章 函数.面向对象.文件操作.深浅拷贝.模块.异常及捕获 第四章 项目打包.类和对象高 ...

  6. android 对象数据库中,解析嵌套的JSON对象,并存储在数据库中的Android

    我只是试图让存储在我的JSON文件中的值,并将其保存到SQLite数据库:解析嵌套的JSON对象,并存储在数据库中的Android 这是我的JSON文件: { "list": { ...

  7. c access mysql数据库_基于C#的Access MsSQL MySQL 三种数据库访问演示(含源文件Demo)...

    基于C#的Access MsSQL MySQL 三种数据库访问演示(含源文件Demo) 一.三种数据库的主要对比 数据库类型 特点 Microsoft Access 桌面数据库.数据库载体是单个文件 ...

  8. 利用json+webservice实现android访问远程数据库,利用JSON+WebService实现Android访问远程数据库...

    2013年第9期SCIENCE&TECHNOLOGYINFORMATION ○IT论坛○科技信息 利用JSON+WebService实现Android访问远程数据库 黄淑静1杨红梅2 (1.山 ...

  9. java开源数据库表描述,HSQLDB 【Java开源 DBMS数据库】

    HSQLDB [Java开源 DBMS数据库] HSQLDB(Hypersonic SQL)是纯Java开发的关系型数据库,并提供JDBC驱动存取数据.支持ANSI-92 标准 SQL语法.而且他占的 ...

最新文章

  1. JavaSript实现调用google地图输入经度,纬度移动到该点,同时对点做标记
  2. Python + wordcloud + jieba 十分钟学会生成中文词云
  3. 【知识图谱】知识推理
  4. 《Ext JS权威指南》——2.1节获取Ext JS 4
  5. 用简单的例子说明提升可复用性的设计模式
  6. vue中使用keepAlive组件缓存遇到的坑
  7. 数学是理工基础,如何才能令人信服?
  8. [设计模式]策略模式
  9. Prototype 字符串
  10. 【BZOJ1014】【tyvj3486】火星人prefix,Splay+字符串hash
  11. echart饼图标签重叠_怎么让ECharts饼图的label标签不重叠?
  12. vs2008 代码对齐方式
  13. 【汇编语言与计算机系统结构笔记16】子程序设计:子程序的嵌套与递归,多个模块之间的参数传送
  14. php openssl_sign() 语法+RSA公私钥加密解密,非对称加密算法详解
  15. 单片机c语言曲普两只蝴蝶,51曲谱网_51单片机简谱编码
  16. 领域驱动设计系列关键概念
  17. 量子计算的基础知识和基本原理
  18. python气象学_Python气象绘图教程(十)
  19. 1.3 网页数据抓取
  20. #RunJS# 最少代码的瀑布流实现

热门文章

  1. winform分页案例简单实现方式~
  2. 简化springboot部署,太灵活方便了!
  3. css实现一级下拉菜单
  4. 基本属性---Linux
  5. 唤醒幻数据包禁用会怎么样_如何利用splashtop实现远程开机、远程唤醒电脑
  6. dplayer js控制 自动全屏_vue-video-player 通过自定义按钮组件实现全屏切换效果【推荐】...
  7. docker 打包镜像_Spring Boot2 系列教程(四十一)部署 Spring Boot 到远程 Docker 容器
  8. AOP切点表达式及通知类参数传递方式
  9. 一篇总结的很好的Spring data jpa 文章,里面包含多种查询方式,可以结合api使用
  10. cognito_将Spring Boot应用程序与Amazon Cognito集成