开发过程中,数据环境会像某人身材那样迅速走样,使测试的结果随之改变。无论是开发人员还是单元测试,都希望数据环境稳定在某个状态。一个方法是写SQL语句来维护,delete * from foo; insert foo (...) values (...),另外一个方法就是非法雇用DBUnit来干这事, Appfuse现在也这么干了。DBUnit可以把预设的数据倒在一个XML文件里,通过简单的ant指令完成维和任务:
<project name="MyProject" default="import" basedir=".">
<taskdef name="dbunit" classname="org.dbunit.ant.DbUnitTask"/>
<target name="import">
<dbunit driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/hr"
userid="hr" password="hr" supportBatchStatement="true">
<classpath><pathelement location="C:\mysql-con-3.0.11.jar"/></classpath>
<operation type="CLEAN_INSERT" src="data.xml"/>
</dbunit>
</target>
</project>
整段的关键是<operation>语句共6种类型,其中CLEAN_INSERT是更彻底的恢复原样,我们主要的维和手段,不过在很多外键很多的时候有点麻烦,要注意表的排列顺序, dbunit是从xml文件的最后删起的.
预设数据可以是手工写就的,也可以从数据库中倒出。怎么看,维护这个XML都比维护长长的SQL语句强。
下面语句不管三七二一,导出全部table。
<dbunit ...> <export dest="export.xml"/> </dbunit>
下面语句导出一个由查询语句产生的DataSet和一个table。
<dbunit ...>
<export dest="partial.xml">
<query name="FOO" sql="SELECT * FROM FOO WHERE last_name='Marquiss'"/>
<table name="FOO123"/>
</export>
</dbunit>
说是非法雇用,因为DBUnit属于JUnit一脉,维持数据库稳定只是它的副作用。
它主要作用还是写TestCase。通过它特有的
public static void assertEquals(ITable expected, ITable actual)
public static void assertEquals(IDataSet expected, IDataSet actual)
比较数据库中的数据是否符合预设的数据。不过因为Oracle Sequence的一往无前,这个功能我还没有用到(除非每次测试都把Sequence删掉重建并滚动到恰当的位置)
所以,在单元测试中, DBUnit更多的责任也还是负责数据库的稳定,用DatabaseOperation类执行刚才提到的操作,其中还要解决中文问题,详见下文.
另,Oracle的数据库必须写schema.