在开展测试过程中,要考虑的第一环节就是测试数据的准备。毫无疑问的,我们可以采用最基本的JDBC连接Oracle数据库,用insert语句完成数据的插入。例如下面这段代码:
示例代码 插入一条记录
01 public void insertData() throws Exception{
02 String dbUrl = "jdbc:oracle:thin:@10.0.4.194:1521:test";
03 String user = "uid";
04 String passwd = "pwd";
05 Class.forName("oracle.jdbc.driver.OracleDriver");
06 Connection c = DriverManager.getConnection(dbUrl,user,passwd);
07 Statement s = c.createStatement();
08 String sql = "insert into TABLE (id, name) values('001', 'mike')";
09 s.executeUpdate(sql);
10 }
但是这种方式有着明显的局限性:
1. 不适合大批量的测试数据准备。
2. 测试数据与代码没有分离。
3. 在代码中维护表结构和表之间的关系非常不妥,当表结构发生变动,代码需要做大量重构工作。
4. 没有断言功能,需要自己编写代码检查测试结果。
我们使用DbUnit来解决上述问题。DbUnit是用于维护测试环境的自动化工具,它本身是一个开源项目。这里我们介绍DbUnit最常用的功能。
用DbUnit插入测试数据
DbUnit支持多种方式向数据库中插入数据,例如FlatXmlDataSet, DTDDataSet等等。这里采用最常用的FlatXmlDataSet。顾名思义,这种方式就是用xml的方式准备数据,DbUnit载入xml文件并完成插入数据库的操作。
首先需要准备一份xml的数据文件,格式如下:
示例代码 数据文件dataset.xml
1 <?xml version="1.0" encoding="GB2312"?>
2 <dataset>
3 <TABLE id="001" name="mike" />
4 <TABLE id="002" name="jack" />
5 </dataset>
第2行的dataset标签是xml的根节点,对应于DbUnit中的一个FlatXmlDataSet对象。
第3行表示要插入的一条记录。其中表名为TABLE,插入的字段为id、name,对应的值分别为“001”、“mike”。
整个xml文件一共插入两条记录。
注意
Xml文件中的值必须用双引号,DbUnit会根据实际的表结构进行类型转换。DbUnit无法插入空值,只能跳过该字段。
接下来要做的就是载入这份数据文件。
示例代码 载入xml文件中的数据
1 public IDataSet getDataSet(String path) {
2 FlatXmlDataSet dataSet = null;
3 try {
4 dataSet = new FlatXmlDataSet(new FileInputStream(new File(path)));
5 } catch (Exception e) {
6 e.printStackTrace();
7 }
8 return dataSet;
9 }
第2行声明一个FlatXmlDataSet对象用来装载测试数据。
第4行用FlatXmlDataSet的构造函数读取path指定的文件来初始化dataSet对象。
第8行返回载有数据的对象。
最后就是连接数据库,将对象中的数据插到数据库中。代码8.5给出了一份较完整的代码。
示例代码 DbUnit.java �CinsertData
01 package util;
02
03 ...
04
05 public class DbUnit {
06 private IDatabaseTester databaseTester;
07
08 private IDatabaseConnection connection;
09
10 private QueryDataSet queryDataSet;
11
12 private String driver;
13
14 private String url;
15
16 private String user;
17
18 private String password;
19
20 private Connection jdbcConnection;
21
22 public DbUnit() {}
23
24 public DbUnit(String driver, String url, String user, String password) {
25
26 try {
27 Class driverClass = Class.forName(driver);
28 jdbcConnection = DriverManager.getConnection(url, user, password);
29 } catch (Exception e) {
30 e.printStackTrace();
31 }
32 }
33
34 public void setSchema(String schema) throws SQLException {
35 connection = new DatabaseConnection(jdbcConnection, schema);
36 }
37
38 public void insertData(IDataSet dataSet) {
39 try {
40 //DatabaseOperation.DELETE.execute(connection, dataSet);
41 DatabaseOperation.INSERT.execute(connection, dataSet);
42 } catch (Exception e) {
43 e.printStackTrace();
44 }
45 }
46
47 public void deleteData(IDataSet dataSet) {
48 try {
49 DatabaseOperation.DELETE.execute(connection, dataSet);
50 } catch (Exception e) {
51 e.printStackTrace();
52 }
53 }
54
55 public void updateData(IDataSet dataSet) {
56 try {
57 DatabaseOperation.UPDATE.execute(connection, dataSet);
58 } catch (Exception e) {
59 e.printStackTrace();
60 }
61 }
62 }
63
64 public QueryDataSet getQueryDataSet() {
65 return queryDataSet;
66 }
67
68 public IDataSet getDataSet(String path) {
69 FlatXmlDataSet dataSet = null;
70 try {
71 dataSet = new FlatXmlDataSet(new FileInputStream(new File(path)));
72 } catch (Exception e) {
73 // TODO Auto-generated catch block
74 e.printStackTrace();
75 }
76 return dataSet;
77 }
第24-32行建立一个jdbc连接到指定的数据库,DbUnit将jdbcConnection对象封装成自身的通用数据库接口对象IDatabaseConnection。
第34-36行,定义setSchema方法完成不同schema之间的切换。
第38-45行,传入数据库连接和数据这个两参数,执行INSERT操作完成最终的插入动作。DatabaseOpeartion中还定义了UPDATE、DELETE等其他常用操作,这些操作都是DatabaseOperation类中的静态成员对象。DbUnit中的具体实现这里就不细讲了,有兴趣的可以参考DbUnit源代码。