用 dbunit-maven-plugin 来管理你的测试数据
单元测试有人写过,也有人没做过,数据库的 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 文件:
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 插件配置中加上:
因为 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. 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's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
这里我们来看 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<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>cc.unmi</groupId>
5 <artifactId>testdbunit</artifactId>
6 <name>TestDbuni</name>
7 <version>0.0.1-SNAPSHOT</version>
8 <build>
9 <plugins>
10 <plugin>
11 <groupId>org.codehaus.mojo</groupId>
12 <artifactId>dbunit-maven-plugin</artifactId>
13 <version>1.0-beta-3</version>
14 <configuration>
15 <driver>com.mysql.jdbc.Driver</driver>
16 <url>jdbc:mysql://localhost/wptest?zeroDateTimeBehavior=convertToNull</url>
17 <username>root</username>
18 <password></password>
19 <dataTypeFactoryName>org.dbunit.ext.mysql.MySqlDataTypeFactory</dataTypeFactoryName>
20 <metadataHandlerName>org.dbunit.ext.mysql.MySqlMetadataHandler</metadataHandlerName>
21 <encoding>utf-8</encoding>
22 <src>target/dbunit/export.xml</src><!--compare 和 operation 要用到它 -->
23 <type>CLEAN_INSERT</type><!--operation 要用到它-->
24 </configuration><br/><br/>
25 <dependencies>
26 <dependency>
27 <groupId>mysql</groupId>
28 <artifactId>mysql-connector-java</artifactId>
29 <version>5.1.13</version>
30 </dependency>
31 </dependencies>
32 </plugin>
33 </plugins>
34 </build>
35</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<executions>
2 <execution>
3 <phase>process-test-classes</phase>
4 <goals>
5 <goal>operation</goal>
6 </goals>
7 <!-- specific configurations 我们可以在这里指定不同的配置-->
8 <configuration>
9 <format>xml</format>
10 <src>src/export.xml</src>
11 <type>CLEAN_INSERT</type>
12 </configuration>
13 </execution>
14</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<tables>
2 <table>
3 <name>wp_users</name>
4 <name>wp_posts</name>
5 </table>
6</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's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。