単体テストを簡単に Unitils 〜データベーステスティング 3 〜

前回の
blog1.mammb.com
からの続きです。

テスト結果の検証

@ExpectedDataSetアノテーションを利用することで、テストメソッド後で、データベースにあるデータの検証懸賞を行うことができます。多くのレコードに対する assert 文を書くことなく、データベース中にある想定されるレコード状態をXMLにて指定します。
ItemDaoTest.xml として以下のXMLがあり、

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
    <item name="item1" />
    <item name="item2" />
</dataset>


以下のようなテストメソッドを実行します。

    @Test
    @ExpectedDataSet
    @DataSet("ItemDaoTest.xml")
    public void testSave() {
        Item item = new Item();
        item.setName("item3");
        Item result = itemDao.save(item);
    }
}


この時、テストケースと同じディレクトリに ItemDaoTest.testSave-result.xml という以下の内容のXMLを用意しておきます。

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
    <item id="1" name="item1" />
    <item id="2" name="item2" />
    <item id="3" name="item3" />
</dataset>

テストメソッド終了後に、データベースの状態がXMLの内容となっているかどうかが検証されます。検証用のXMLは、<クラス名>.<テストメソッド名>-result.xml という命名となっている必要があります。


データソースの取得

@TestDataSource アノテーションを使用することで、テストケースから javax.sql.DataSource を取得することができます。以下のような実装となります。

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class ItemDaoTest {
    @TestDataSource
    private DataSource dataSource;
}


また、別な方法として DatabaseUnitils というユーティリティクラスを使うこともできます。

    DatabaseUnitils.getDataSource();

トランザクション

Unitils によるテストケースでは、デフォルトでテストメソッド毎にコミットされます。
以下の例では、testSave() によるデータがコミットされるため、testGet() メソッドは成功します。

    @Test
    @Transactional(TransactionMode.ROLLBACK)
    public void testSave() {
        Item item = new Item();
        item.setName("item1");
        itemDao.save(item);
    }

    @Test
    public void testGet() {
        Item result = itemDao.get(1L);
        assertPropertyLenientEquals("name", "item1", result);
    }


testSaveメソッドに以下のように @Transactional アノテーションを付与し、ロールバックを指定することで、testSavaメソッドの結果はロールバックされ、testGet() メソッドは失敗するようになります。

    @Test
    @Transactional(TransactionMode.ROLLBACK)
    public void testSave() {


デフォルトの振る舞いを変更するには、Unitils.properties にて以下の指定を行うことで、テストメソッド毎にロールバックされるようになります。

DatabaseModule.Transactional.value.default=rollback


この場合は、とすることで、個々のメソッド単位でCOMMITさせることもできます。

    @Transactional(TransactionMode.COMMIT)