資料集建立與取得


DbUnit 可以使用XML建立資料集,DbUnit提供了許多建立資料集的方式,其中最常用的是XmLDataSetFlatXmlDataSet。首先看到XmlDataSet的建 立所需的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dataset SYSTEM "dataset.dtd">
<dataset>
<table name="t_bookmark">
<column>id</column>
<column>url</column>
<column>title</column>
<column>category</column>
<row>
<value>1</value>
<value>http://a</value>
<value>b</value>
<value>c</value>
</row>
<row>
<value>2</value>
<value>http://x</value>
<value>y</value>
<value>z</value>
</row>
</table>
</dataset>

其中dataset.dtd如下:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT dataset (table+) | ANY>
<!ELEMENT table (column*, row*)>
<!ATTLIST table
name CDATA #REQUIRED
>
<!ELEMENT column (#PCDATA)>
<!ELEMENT row (value | null | none)*>
<!ELEMENT value (#PCDATA)>
<!ELEMENT null EMPTY>

如果想要讀取這樣的XML文件,可以使用XmLDataSet。例如:
IDataSet dataSet = new XmlDataSet(new FileInputStream("dataset.xml"));

然而這樣建立的XML文件太冗長而不易撰寫,你可以採用FlatXmlDataset的格式,撰 寫起來比較簡潔:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<t_bookmark id="1" url="http://a" title="b" category="c"/>
<t_bookmark id="2" url="http://x" title="y" category="z"/>
</dataset>

如果想要讀取這樣的XML文件,可以使用FlatXmLDataSetBuilder。例如:
IDataSet dataSet = new FlatXmlDataSetBuilder()
                         .build(new FileInputStream("dataset.xml"));


IDataSet代 表著資料集合,資料集合的來源可能是XML文件或資料庫。你可以從XML文件建立IDataSet實作物件, 再將之安插至資料庫中。例如 使用 DbUnit 中看到的片段:
    ...
        // 讀取指定的資料集合
    private static IDataSet getXMLDataSet(String file) throws Exception {
        return new FlatXmlDataSetBuilder()
                       .build(new FileInputStream(file));
    }

    @Before
    public void setUp() throws Exception {
        // 測試前讀入初始資料集合、清除表格並將初始資料集合新增至資料庫中的表格
        DatabaseOperation.CLEAN_INSERT.execute(dbConn, getXMLDataSet("dataset.xml"));
        dao = new BookmarkDAOImpl(dataSource);
    }
    ...

如果你有一個IDatabaseConnection 實作物件,可以呼叫createDataSet(),這會取得資料庫的資料,並建立IDataSet實作物件,如果你想要將之寫至XML文件,則可以利用XmlDataSetWriterFlatXmlWriter的write()方法。例如:
// dbConn是IDatabaseConnection實作物件
IDataSet dataSet = dbConn.createDataSet();
new FlatXmlWriter(new FileOutputStream("some.xml")).write(dataSet);

如 果不想將資料庫中的資料全部用來建立IDataSet,則呼叫createDataSet()時可以指定表格:
IDataSet dataSet = dbConn.createDataSet(new String[] { "t_bookmark" });

也可以使用QueryDataSet。例如:
// dbConn是IDatabaseConnection實作物件
QueryDataSet dataSet = new QueryDataSet(dbConn);
// 將
a_table加入資料集
dataSet.addTable("a_table");
// 將SELECT出的資料加入資料集
dataSet.addTable("t_bookmark", "SELECT * FROM t_bookmark WHERE id < 10");

如果有一個現成的 IDataSet,則可以使用FilteredDataSet來過 濾。例如:
FilteredDataSet filteredDataSet = new FilteredDataSet(
        new String[] {"t_bookmark"}, dataSet);

如果在設定XML時,某些值暫時無法確定,例如在 使用 DbUnit 中看到的片段:
    ...
    @Test

    public void testAdd() throws Exception {
        // 用待測的DAO安插資料
        Bookmark bookmark = new Bookmark("http://m", "n", "o");
        dao.add(bookmark);

        // 用 DbUnit 取得資料
        IDataSet dataSet = databaseTester.getConnection().createDataSet();
        // 讀取預期資料集合
        IDataSet expected = getXMLDataSet("expected.xml");
        // 斷言資料集合相等性,但忽略id欄位
        assertEqualsIgnoreCols(expected, dataSet,
                "T_BOOKMARK", new String[] {"id"});
    }
    ...

由於資料庫中的 id是自動遞增,因此在上面的片段中忽略了id欄位來進行比較。另一個方式是使用ReplacementDataSet, 替代掉資料集中的id值。例如你可以先在expected.xml中如下撰寫:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<t_bookmark id="1" url="http://a" title="b" category="c"/>
<t_bookmark id="2" url="http://x" title="y" category="z"/>
<t_bookmark id="[ID]" url="http://m" title="n" category="o"/>
</dataset>

之後在 testAdd()中取代掉[ID]的值:
    ...
    @Test

    public void testAdd() throws Exception {
        // 用待測的DAO安插資料
        Bookmark bookmark = new Bookmark("http://m", "n", "o");
        dao.add(bookmark);

        // 用 DbUnit 取得資料
        IDataSet dataSet = databaseTester.getConnection().createDataSet();
        // 取得表格資料
        ITable table = dataSet.getTable("T_BOOKMARK");
        // 取得最後一筆資料的id值
        Integer lastId = (Integer) table.getValue(table.getRowCount() - 1, "id");
       
        // 讀取預期資料集合
        IDataSet expected = getXMLDataSet("expected.xml");
        ReplacementDataSet replacementDataSet = new ReplacementDataSet(expected);
        // 取代[ID]值
        replacementDataSet.addReplacementObject("[ID]", lastId);
        expected = replacementDataSet;
       
        // 斷言資料集是否相等
        Assertion.assertEquals(expected, dataSet);
    }
    ...


你也可以為FlatXMLDataSet產 生DTD檔案。例如:
new FlatDtdWriter(new FileWriter("some.dtd")).write(dataSet);

一個產生的DTD檔案範例如下:
<!ELEMENT dataset (
t_bookmark*)>

<!ELEMENT t_bookmark EMPTY>
<!ATTLIST t_bookmark
id CDATA #REQUIRED
url CDATA #REQUIRED
title CDATA #REQUIRED
category CDATA #REQUIRED
>

如果你想要將XML置於Classpath,則可以使用DataFileLoader來 取得。例如:
DataFileLoader loader = new FlatXmlDataFileLoader();
IDataSet dataSet = loader.load("dataSet.xml"); // dataSet.xml置於Classpath中