dbunit简介及使用

【概念】
dbunit是一个基于junit扩展的数据库测试框架。它提供了大量的类对与数据库相关的操作进行了抽象和封装,虽然在80%的情况,你只需使用它极少的api。它通过使用用户自定义的数据集以及相关操作使数据库处于一种可知的状态,从而使得测试自动化、可重复和相对独立。虽然不用dbunit也可以达到这种目的,但是我们必须为此付出代价(编写大量代码,测试及维护),既然有了这么优秀的开源框架,我们又何必再造轮子。
DbUnit是为数据库驱动的项目提供的一个对JUnit 的扩展,除了提供一些常用功能,它可以将你的数据库置于一个测试轮回之间的状态。
【简介】
为依赖于其他外部系统(如数据库或其他接口)的代码编写单元测试是一件很困难的工作。在这种情况下,有效的单元必须隔离测试对象和外部依赖,以便管理测试对象的状态和行为。
使用mock object对象,是隔离外部依赖的一个有效方法。如果我们的测试对象是依赖于DAO的代码,mock object技术很方便。但如果测试对象变成了DAO本身,又如何进行单元测试呢?
开源的DbUnit项目,为以上的问题提供了一个相当优雅的解决方案。使用DbUnit,开发人员可以控制测试数据库的状态。进行一个DAO单元测试之前,DbUnit为数据库准备好初始化数据;而在测试结束时,DbUnit会把数据库状态恢复到测试前的状态。
【原理】
dbunit的与单元测试相关的两个最重要的核心是org.dbunit.database.IDatabaseConnection 和 org.dbunit.dataset.IDataSet ,前者是产品代码使用的数据库连接的一个简单的封装,后者是对单元测试人员自定义的数据集(通常以xml文件的形式存在,且xml文件的格式也有好几种)的封装。
还有一个很重要的咚咚就是org.dbunit.operation.DatabaseOperation,该类是一个抽象类代表了对数据库的操作,例如CUD以及其组合等, 它采用了退化的工厂模式,可直接通过它获取其具体的子类(代表具体的某种操作)如下:
DatabaseOperation.UPDATE
DatabaseOperation.DELETE
DatabaseOperation.DELETE_ALL
DatabaseOperation.TRUNCATE
DatabaseOperation.REFRESH
DatabaseOperation.CLEAN_INSERT
DatabaseOperation.NONE
工作流程如下:
1)testcase.setup--->testcase.getConnection-->getDataSet----->operation.execute(通常DatabaseOperation.CLEAN_INSERT)
2)testcase.testSomeMethod---->dao.someMethod
3)testcase.teardown---->operation.execute(通常DatabaseOperation.DELETE_ALL或者DatabaseOperation.NONE)


下面是一个Step by Step的教程

1、导入jar包

dbunit必需jar下载

2、建数据库

create database junit_db default character set UTF8;
use junit_db;
create table j_user(username varchar(50), password varchar(50), nickname varchar(50));
3、创建实体

package com.lxh.model;

public class User {
	private String username;
	private String password;
	private String nickname; ....
}

4、创建数据库连接的工具类

package com.lxh.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DbUtil {
	public static Connection getConnection() throws SQLException {
		Connection con = null;
		con = DriverManager.getConnection("jdbc:mysql://localhost:3306/junit_db?useUnicode=true&characterEncoding=utf8", "root", "root");
		return con;
	}

	public static void close(Connection con) {
		try {
			if (con != null) {
				con.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static void close(PreparedStatement ps) {
		try {
			if (ps != null) {
				ps.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static void close(ResultSet rs) {
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

5、创建dbunit的测试数据xml文件,并将文件存储在类路径下的dbunit_xml/j_user.xml中(这个路径随便放,只要在读取文件的时候能读取到就行)

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
	<j_user username="admin" password="123" nickname="管理员"/>
</dataset>
dbunit的XML属性支持两种格式的描述:基于XML节点的数据描述;基于XML属性的数据描述。这里展示的是基于XML属性的数据描述。


6、在测试中dbunit的基本使用步骤:(1)、备份数据库 (2)、导入测试基本数据 (3)、还原数据库 (4)、执行测试案例,接下来就按照这个顺序一一展示dbunit的神秘

6.1、备份数据库

6.1.1、备份整个数据库

@Test
	public void testBackupAllTable() {
		try {
			// jdbc的数据库连接
			Connection conn = DbUtil.getConnection();
			// 创建dbunit的Connection,需要传入数据库连接
			IDatabaseConnection jconn = new DatabaseConnection(conn);
			// 从dbunit的连接中获取数据集,因为是从数据库连接中获取的数据集,所以数据集就是整个数据库
			IDataSet ds = jconn.createDataSet();
			// 将整个数据集中的数据导出到E:\\db_backup.xml文件中,并设置编码为UTF-8
			FlatXmlDataSet.write(ds, new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:\\db_backup.xml"), "UTF-8")));
		} catch (DataSetException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (DatabaseUnitException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

将这个备份数据的操作做成一个TestCase了,这样就实现了整个数据库的备份,数据的所有数据将会备份到 E:\\db_backup.xml文件中。

6.1.2、备份制定的数据库表

@Test
	public void testBackUpTable() {
		try {
			// jdbc的数据库连接
			Connection conn = DbUtil.getConnection();
			// 创建dbunit的Connection,需要传入数据库连接
			IDatabaseConnection jconn = new DatabaseConnection(conn);
			// 通过QueryDataSet可以有效的选择要处理的表作为数据集
			QueryDataSet backup = new QueryDataSet(jconn);
			// 添加j_user这张表作为备份表
			backup.addTable("j_user");
			FlatXmlDataSet.write(backup, new BufferedWriter(
					new OutputStreamWriter(
							new FileOutputStream("E:\\db_backup.xml"), "UTF-8")));
		} catch (AmbiguousTableNameException e) {
			e.printStackTrace();
		} catch (DataSetException e) {
			e.printStackTrace();
		} catch (DatabaseUnitException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


同时可以添加多张表,这样就能实现备份指定的表了

6.2、导入测试基本数据

@Test
	public void testLoad() {
		try {
			// jdbc的数据库连接
			Connection conn = DbUtil.getConnection();
			// 创建dbunit的Connection,需要传入数据库连接
			IDatabaseConnection jconn = new DatabaseConnection(conn);
			// FlatXmlDataSet是用来获取基于属性存储的属性值 XMLDataSet用来获取基于节点类型存储的属性值
			IDataSet ds = new FlatXmlDataSet(
					new FlatXmlProducer(
							new InputSource(
									new BufferedReader(
											new InputStreamReader(
													this.getClass().getClassLoader().getResourceAsStream("dbunit_xml/j_user.xml"), "UTF-8")
											)
									)
							)
					);
			// 将数据的数据清空,并且把测试数据插入
			DatabaseOperation.CLEAN_INSERT.execute(jconn, ds);
		} catch (DataSetException e) {
			e.printStackTrace();
		} catch (DatabaseUnitException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

通过这个方法,我们就可以把 E:\\db_backup.xml中的数据作为基本数据先导入到数据,为单元测试做准备数据

6.3、还原数据库

在进行完我们的所有测试工作后,我们需要将数据库还原,这个时候就要用到我们备份数据库时生成的备份XML文件了

@Test
	public void testResume() {
		try {
			// jdbc的数据库连接
			Connection conn = DbUtil.getConnection();
			// 创建dbunit的Connection,需要传入数据库连接
			IDatabaseConnection jconn = new DatabaseConnection(conn);
			// 根據備份文件創建dataset
			IDataSet ds = new FlatXmlDataSet(
					new FlatXmlProducer(
							new InputSource(
									new BufferedReader(
											new InputStreamReader(
													new FileInputStream("E:\\db_backup.xml"), "UTF-8")))));
			DatabaseOperation.CLEAN_INSERT.execute(jconn, ds);
		} catch (DataSetException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (DatabaseUnitException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

将e://db_backup.xml文件重新导入数据库,就实现了数据库的还原操作。


6.4、通过以上几个步骤的操作,我们现在已经可以写做一个完成整的与数据库隔离的测试代码了


@Test
	public void testDbUnit() throws Exception {
		// 备份数据库
		testBackUpTable();
		// 加载测试数据
		testLoad();
		// 进行测试
		IUserDao ud = new UserDaoImpl();
		User tu = ud.load("admin");
		assertEquals(tu.getUsername(), "admin");
		assertEquals(tu.getPassword(), "123");
		assertEquals(tu.getNickname(), "管理员");
		// 还原数据库
		testResume();
	}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 测试环境的搭建(DBunit+HSQLDB) 1 1.1. DBunit简介 1 1.1.1. DBunit简单介绍和原理 1 1.1.2. DBunit的三大核心组件 1 1.1.3. DBunit的安装使用 2 1.2. HSQLDB简介 3 1.2.2. 什么是HSQLDB 3 1.2.3. HSQLDB安装和使用 5 1.2.4. HSQLDB使用 7 1.2.5. HSLDB的使用注意事项 8 2. 数据库单元测试测试流程介绍 1 2.1. 数据库单元测试的原因 1 2.2. 测试关注点 1 2.3. 测试流程 1 3. 数据库单元测试最佳实践 2 3.1. 数据库单元测试最佳实践 2 3.1.1. 从“易测试的”应用程序体系结构开始。 2 3.1.2. 使用精确的断言。 2 3.1.3. 外化断言数据。 3 3.1.4. 编写全面的测试。 4 3.1.5. 创建稳定、有意义的测试数据集。 5 3.1.6. 创建专用的测试库。 6 3.1.7. 有效地隔离测试。 7 3.1.8. 分割测试套件。 8 3.1.9. 使用适当的框架(如 DbUnit)简化过程。 9 3.2. DBunit使用最佳实践 9 3.2.1. 每一个开发人员需要搞一个数据库实例。 9 3.2.2. 使用XML文件作为DataSet 9 3.2.3. DBUnit的最佳实践是尽可能使用最小的数据集。 10 3.2.4. DatabaseOperation.CLEAN_INSERT 策略 10 3.2.5. 为相互关联的测试场景创建多个种子文件是一个很有效的策略. 10 3.3. 自我总结 10 3.3.1. 对各种类型的方法的测试策略: 10 3.3.2. 写一个基TestCase。 10 3.3.3. 测试数据库的有效方法。 10 3.3.4. seed文件的设置 10 3.3.5. 一般的测试的步骤 11 4. 常见问题 1 4.1. DBUnit使用问题 1 4.1.1. 在运行测试用例的时候,出现org.dbunit.dataset.DataSetException: java.net.MalformedURLException at……………类似的异常? 1 4.1.2. 在运行测试用例的时候,出现SQLException,并且对应的sqlstate:23504,这是为什么? 1 4.2. HSQLDB相关的问题 1 4.2.1. 抛出:java.sql.SQLException: socket creation error 1 4.3. 其他问题 1
可以使用以下步骤将 Dbunit 集成到 Spring Boot 中: 1. 添加依赖项:在 pom.xml 文件中添加以下依赖项。 ```xml <dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-version}</version> <scope>test</scope> </dependency> ``` 2. 创建测试数据集:在 src/test/resources 目录下创建测试数据集。例如,创建名为 `dataset.xml` 的测试数据集。 ```xml <dataset> <table name="users"> <column>id</column> <column>name</column> <column>email</column> <column>age</column> <column>created_at</column> <column>updated_at</column> <row> <value>1</value> <value>test1</value> <value>[email protected]</value> <value>20</value> <value>2021-01-01 00:00:00</value> <value>2021-01-01 00:00:00</value> </row> <row> <value>2</value> <value>test2</value> <value>[email protected]</value> <value>30</value> <value>2021-01-01 00:00:00</value> <value>2021-01-01 00:00:00</value> </row> </table> </dataset> ``` 3. 创建测试类:创建名为 `UserRepositoryTest` 的测试类,并添加以下代码。 ```java @RunWith(SpringRunner.class) @SpringBootTest @DatabaseSetup("/dataset.xml") public class UserRepositoryTest { @Autowired private UserRepository userRepository; @Test public void testFindAll() { List<User> users = userRepository.findAll(); assertEquals(2, users.size()); } // other test methods } ``` 4. 运行测试:运行测试类,测试应该能够成功运行。 以上就是整合 Dbunit 到 Spring Boot 的步骤,希望能够对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值