单元测试有人写过,也有人没做过,数据库的 dbunit 的用的人应该更少了,它可以用来给你做测试准备数据。一般我们做测试会在一个测试数据库中不停的测,自然会累积许多垃圾数据,给单元测试会造成不便,功能测试倒无太紧要。如果我们想在单元测试的时候有一份干净的数据,有个做法是搞个备用的数据库,测试前导到测试库的,或用某些数据库的导入导出功能。
这里我们来看 dbunit 怎么实现准备测试数据的,它可以用来导出数据库数据到数据文件中,从数据文件中导入干净的数据到数据库中,比较数据库与数据文件、或增量的插入记录等等。
dbunit 最初为 ant 提供了 antask,当然可以编程使用,如今 maven 大行其道,所以也就有了 maven 的 dbunit 插件,相似功能的插件有两个:
1. dbunit-maven-plugin
2. maven-dbunit-plugin
就是 maven 和 dbunit 倒了一下,别晕了,第二个似乎提供了更多的 goal,但运行 mvn dbunit:xxxx,指向的是第一个 dbunit-maven-plugin,看来第一个要正统些。本文也就介绍下 dbunit-maven-plugin 的用法,测试数据库是 MySql。
看我们的 pom.xml 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cc.unmi</groupId> <artifactId>testdbunit</artifactId> <name>TestDbuni</name> <version>0.0.1-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>dbunit-maven-plugin</artifactId> <version>1.0-beta-3</version> <configuration> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://localhost/wptest?zeroDateTimeBehavior=convertToNull</url> <username>root</username> <password></password> <dataTypeFactoryName>org.dbunit.ext.mysql.MySqlDataTypeFactory</dataTypeFactoryName> <metadataHandlerName>org.dbunit.ext.mysql.MySqlMetadataHandler</metadataHandlerName> <encoding>utf-8</encoding> <src>target/dbunit/export.xml</src><!--compare 和 operation 要用到它 --> <type>CLEAN_INSERT</type><!--operation 要用到它--> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.13</version> </dependency> </dependencies> </plugin> </plugins> </build> </project> |
dbunit-maven-plugin 有四个 goal,分别是:
dbunit:compare 比较数据库与数据文件中的内容,相同则提示成功,不同则报异常
dbunit:export 导出数据库内容到数据文件中,默认是 xml 格式的数据
dbunit:help 看帮助的,要看 goal 的更详细的帮助可用:mvn dbunit:help -Ddetail=true -Dgoal=<goal-name>
dbunit:operation 可用来执行数据库操作,如 插入、清除数据,清除并插件数据等。用的多的应该是 CLEAN_INSERT,可得到一份干净的数据库。
上面的 pom.xml 是一个基本的配置,未指定的会使用默认值,例如导出数据的目的地是 <dest>target/dbunit/export.xml</dest>,点击每个 goal 的链接可以看到可以加到 <configuration> 节点中更多的配置项。
好了,现在有了 pom.xml 文件就可以用来执行相应的 goal 了,在命令行下进到这个 pom.xml 所在的目录中:
执行 mvn dbunit:export 你会看到生成了一个 target/dbunit/export.xml,包含了库中所有表的数据。
执行 mvn dbunit:compare 会将 <src> 指定的数据文件与数据库内容对比,相同则提示成功,不同就会报异常,由于我们上面指定的源文件是刚刚导出的 target/dbunit/export.xml,所以比较是成功的。
现在把数据库清空掉,然后执行 mvn dbunit:operation 后,你会发现数据库中的内容又原来的一样,是因为这个命令把数据文件 <src> 指示的 target/dbunit/export.xml 的数据导入到了数据库中。其实在执行 CLEAN_INSERT 时会先把数据库中的数据清理掉的。
dbunit:operation goal 的 type 取值有:UPDATE, INSERT, DELETE, DELETE_ALL, REFRESH, CLEAN_INSERT, MSSQL_INSERT, MSSQL_REFRESH, MSSQL_CLEAN_INSERT,你可以尝试一下其他值产生的效果,有些很容易理解用途的。
可能出现的异常,比如当执行 mvn dbunit:export 有 ERROR 时,请加上 -e 参数执行,mvn dbunit:export -e (要是执行 mvn dbunit:export -X 会有更多的信息)你将会看到详细的异常栈。例如碰到:
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
就应该知道是驱动没找到,只要加到对 MySql 驱动的依赖就行。
你要是看到:
Caused by: java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 8 to TIMESTAMP.
Caused by: java.sql.SQLException: Value '[B@297ffb' can not be represented as java.sql.Timestamp
这样的错误,那要请为你的 MySql jdbc 链接字符串加上属 zeroDateTimeBehavior=convertToNull。关于 MySql 的属性请参考文章下端列出的链接。
然而,有时候我们并不会直接去呼叫 dbunit:export 这样的 goal,我们会在某个 phase 之后来执行这个 goal,以 dbunit:export 为例,那就要在 pom.xml 中的 dbunit-maven-plugin 插件配置中加上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<executions> <execution> <phase>process-test-classes</phase> <goals> <goal>operation</goal> </goals> <!-- specific configurations 我们可以在这里指定不同的配置--> <configuration> <format>xml</format> <src>src/export.xml</src> <type>CLEAN_INSERT</type> </configuration> </execution> </executions> |
因为 phase 也是按顺序执行的,这里设置的 goal 是 process-test-classes,所以当我们在执行 mvn process-test-classes 后会调用这个 dbunit:operation goal。而当我们执行 mvn test 时,会发现这个 dbunit:operation 会在 test 之前执行,这能也就能为我们准备好单元测试的数据了,不会因为小动了下数据库而让 test 全线告错。
对于另外两个 goal,dbunit:compare 和 dbunit:export 也可以采用类似的配置,让某个 phase 来调用。
最后,留意下每个 goal 的所有配置以及相应的默认值,比如在执行 dbunit:export 时可以用 <schema> 指定导出哪些表,再严格点可以用
1 2 3 4 5 6 |
<tables> <table> <name>wp_users</name> <name>wp_posts</name> </table> </tables> |
指定导出某些特定的表。
参考:1. Maven plugin中的lifecycle、phase、goal、mojo概念及作用的理解
2. Guide to Developing Java Plugins
3. Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J
本文链接 https://yanbin.blog/dbunit-maven-test-data/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。