Java Top.

开始使用Spring 5和Spring Boot 2,通过学习春天课程:

>>查看课程

1.介绍

在本教程中,我们将看一下DBUNIT,一个用于的单元测试工具测试关系数据库交互Java。

我们将看到它如何帮助我们将数据库转换为已知状态并对预期状态进行断言。

2.依赖关系

首先,我们可以通过添加达到Maven Central的Dbunit来添加DBUNITdbunit.依赖我们的依赖pom.xml:

<依赖>  org.dbunit   DBUNIT   2.7.0   test  

我们可以查找最新版本Maven Central.

3.你好世界例

接下来,我们来定义a数据库架构:

schema.sql.:

创建表如果不存在客户端(`id` int auto_increment not null,`first_name`varcar(100)不是null,`last_name`varcar(100)不是null,主键(`id`);创建表(如果不存在项目)(`id` int auto_increment not null,`标题`varchar(100)不是null,`spected`日期,`price float,主键(`id`);

3.1。定义初始数据库内容

DBUnit允许我们在一个简单的数据库中定义和加载测试数据集声明方式

我们用一个XML元素定义每个表行,其中标记名是表名,属性名和值分别映射到列名和值。可以为多个表创建行数据。我们必须实现getDataset()的方法DataSourceBasedDBTestCase要定义初始数据集,我们可以使用它FlatXmlDataSetBuilder要引用我们的XML文件:

data.xml.:

< ?xml version = " 1.0 " encoding = " utf - 8 " ?>        

3.2。初始化数据库连接和架构

现在我们已经有了我们的模式,我们必须初始化我们的数据库。

我们必须延长DataSourceBasedDBTestCase类并初始化其数据库模式getDataSource ()方法:

datasourcedbunittest.java.:

public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {@Override protected DataSource getDataSource() {JdbcDataSource = new JdbcDataSource();数据源。setturl ("jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'");dataSource.setUser(“sa”);dataSource.setPassword(“sa”);返回数据源;} @Override protected IDataSet getDataSet()抛出异常{返回新的FlatXmlDataSetBuilder().build(getClass().getClassLoader() .getResourceAsStream("data.xml"));}}

在这里,我们将SQL文件传递给其连接字符串中的H2内存数据库。如果我们想在其他数据库上测试,我们需要为它提供我们的自定义实施。

请记住,在我们的例子中,DBUnit将在执行每个测试方法之前用给定的测试数据重新初始化数据库

有多种方法可以配置此功能得到SetUpOperation得到泪滴:

@Override受保护的数据库处理GetsetupOperation(){return datedated.refresh;@Override受保护的数据库operation GetTeardoperation(){return datedated.delete_all;}

刷新操作,告诉DBUnit刷新它的所有数据。这将确保清除所有缓存,并且我们的单元测试不会受到另一个单元测试的影响。的DELETE_ALL操作确保在每个单元测试结束时删除所有数据。在我们的例子中,我们告诉DBUnit在设置期间,使用getSetUpOperation方法实现时,我们将刷新所有缓存。最后,我们告诉DBUnit在拆卸操作期间使用getTearDownOperation方法实现。

3.3。比较预期的状态和实际状态

现在,让我们来检查我们的实际测试案例。对于第一次测试,我们将保持简单 - 我们将加载我们的期望数据集并将其与DB连接中检索的数据集进行比较:

@Test public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception {IDataSet expectedDataSet = getDataSet();ITable expectedTable = expectedDataSet.getTable(“CLIENTS”);idatasset databaseDataSet = getConnection().createDataSet();ITable actualTable = databaseDataSet.getTable(“客户端”);assertequal (expectedTable actualTable);}

深深潜入断言

在上一节中,我们看到了将表的实际内容与预期数据集进行比较的基本示例。现在,我们将发现DBUNIT的支持对自定义数据断言。

4.1。断言SQL查询

检查实际状态的一种简单方法是使用SQL查询

在此示例中,我们将将新记录插入到客户端表中,然后验证新创建的行的内容。我们定义了预期的产出单独的XML文件,并通过SQL查询提取实际行值:

@test public vivendataset_wheninsert_thentablehasnewclient()抛出异常{try(inputstream是= getClass()。getClassloader()。getresourceastream(“dbunit / periection-user.xml”)){idataset perianeddataset = new flatxmldatasetbuilder()。构建(是);ITable expectedTable = expectedDataSet.getTable(“CLIENTS”);连接conn = getDatasource()。getConnection();conn.createstatement().executeupdate(“插入客户端(first_name,last_name)值('John','Jansen')”);itable vectentydata = getConnection().createCeyTable(“Result_name”,“来自Last_Name ='Jansen'”的客户端选择*);assertequalsignorecols(预期的,实际数据,新字符串[] {“ID”});}}

getConnection()方法的方法dbtestcase.祖先类返回数据源连接的dbunit特定表示(一个idatabaseConnection.实例)。createQueryTable ()方法的方法idatabaseConnection.可以用来从数据库获取实际数据吗,以便与预期的数据库状态进行比较断言.Assertequals()方法。传递的SQL查询createQueryTable ()是我们想要测试的查询。它返回A.桌子我们用来使我们的断言的实例。

4.2。忽略专栏

有时在数据库测试中,我们希望忽略实际表的某些列。这些通常是我们无法严格控制的自动生成的值,如生成的主键或当前时间戳

我们可以通过省略列来做到这一点从SQL查询中的Select Claus中,DBUNIT为实现此目的提供了更方便的实用程序。的静态方法DefaultColumnFilter班级我们可以创造一个新的ITable通过排除一些列来从现有的实例,如这里所示:

@test公共vivendataset_wheninsert_thengetresultsarestillequaliarigningscolumnswithdifferent producceed()抛出异常{connection connection = tester.getConnection()。getConnection();string []排除了dcolumns = {“id”,“生成”};尝试(InputStream是= getClass()。getClassloader().getresourceastream(“dbunit / perminal-ingenoround-nregital_at.xml”)){idataset perianeddataset = new flatxmldatasetbuilder()。构建(是);Itable IdipperableTable =排除诊所静止(预期的DOTASET.GETTABLE(“项目”),排除诊所);connection.createStatement().executeUpdate(“插入项目(标题,价格,生产)值(”项链“,199.99,现在())”);idataset databaseDataset = tester.getConnection()。创建aset();Itable ActualTable =排除诊所静止(DatabaseDataset.gettable(“项目”),排除诊所);assertequal (expectedTable actualTable);}}

4.3。调查多个失败

如果DBUnit找到一个不正确的值,然后它立即抛出一个assertionerror.

在特定的情况下,我们可以使用DiffCollectingFailureHandler类,我们可以将其传递给断言.Assertequals()方法作为第三个参数。

这个失败处理程序将收集所有失败,而不是在第一个失败上停止,这意味着断言.Assertequals()方法总是成功的,如果我们使用DiffCollectingFailureHandler因此,我们必须以编程的方式检查处理器是否发现了任何错误:

@test public vivendataset_wheninsertunexpecteddata_hhenfailonallunexpectedvalues()抛出异常{try(inputstream是= getClass().getclassloader().getcrassloader().getresourceastream(“dbunit / pressult-fallures.xml”))){idataset perianeddataset = new flatxmldatasetbuilder()。构建(是);Itable IdandectialTable = perpectedDataset.gettable(“项目”);连接conn = getDatasource()。getConnection();diffcollectingfailure handler collectinghandler = new diffcollectingfailure handler();conn.createStatement().executeUpdate(“插入物品(标题,价格)值('电池','1000000')”);itable vealthdata = getConnection()。创造了aset()。gettable(“项目”);assertequals(预计,实际数据,CollectingHandler);if(!collectinghandler.getdifflist()。isempty()){string message =(string)collectinghandler.getdifflist().stream().map(d  - > formatdifference((差异)d)).collect(加入(“\n“));logger.Error(() - >消息);}}}私有静态字符串FormatDifference(差异diff){return“在”+ diff.getexpectedtable()中的预期值().gettableMetadata().gettableName()+“。” + diff.getColumnName() + " row " + diff.getRowIndex() + ":" + diff.getExpectedValue() + ", but was: " + diff.getActualValue(); }

此外,处理程序以形式提供故障区别实例,可让我们格式化错误。

运行测试后,我们获得格式化的报告:

assertionerror: ITEMS中的期望值。price row 5:199.99,但是ITEMS中的期望值是:1000000.0。产生行5:2019-03-23,但是:null期望值的项目。title row 5:Necklace, but was: Battery at com.金宝搏188体育baeldung.dbunit.DataSourceDBUnitTest.givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues(DataSourceDBUnitTest.java:91)

需要注意的是,此时我们希望新道具的价格是199.99,但实际价格却是1000000.0。然后我们看到生产日期是2019-03-23,但最后,它是空的。最后,我们期望的东西是一条项链,结果我们得到了一个电池。

结论

在本文中,我们看到DBUNIT如何提供定义测试数据的声明方式测试Java应用程序的数据访问层。

一如既往,可以使用以下示例的完整源代码在github上

Java底部

开始使用Spring 5和Spring Boot 2,通过学习春天课程:

>>查看课程
对这篇文章的评论关闭!