2019.10.07

DB Unit 特徴とプロジェクトに導入する

次世代システム研究室の T.B です。

データベースに関するテストする時DBUnitは一つの方法です。その便利なライブラリの使い方をご紹介します。

あるプロジェクトでテーブルを作成した後、初期データを投入していますが、テストの時初期データ使うのはもちろん制限されますね。

DBUnitを使えば簡単に解決できると思います。

目次

  1.  DBUnitとは
  2.  インストール
  3.  テストで実装するの例
    1. データをバックアップ
    2. テスト用データを追加
    3. バックアップデータでDBを復旧する
  4. DBUnitの操作リスト
  5. まとめ

1. DBUnitとは

JavaでDBのテストを行う際に、DBのデータを簡単に編集できるJUnit拡張機能です。
XMLとかExcelとかにデータを書いておくと、勝手にDBにデータを設定してくれます。
TRUNCATEとかINSERTとかUPDATEとかいろいろできます。

ちなみに、バージョン2.0以降、DbUnitは、ストリーミングモードで使用する場合、大きなデータセットでも機能します。 DBUnitは、データベースのデータセットが期待される値のセットと一致することを確認するのにも役立ちます。

2. インストール

簡単です。

Gradleベースプロジェクトでbuild.gradleファイルに以下の行を追加したらOKです。(もちろんgradleの自動的buildのを1分くらい待ちます。)
testCompile group: 'org.dbunit', name: 'dbunit', version: '2.6.0'

MavenとかSBTとか他の種類も対応できます。以下のリンクでご参考ください。

https://mvnrepository.com/artifact/org.dbunit/dbunit/2.6.0

3. テストで実装するの例

テストの時、簡単なシナリオなら以下の流れになりますね
  1. データをバックアップ (DBUnit)
  2. テスト用データを追加 (DBUnit)
  3. テストコード実施
  4. 期待するデータと実際もらうデータを比較
  5. バックアップデータでDBを復旧する (DBUnit)
3, 4はあなたの実装コードですから、今度はDBUnitに関する実装しますので、1, 2, 5をしてみましょう。

ちなみに、DBUnit操作のリストは最後のところにありますが、使用する際、紹介したほうがわかりやすいと思いますので、1を始めましょう。

3.1 データをバックアップ

テストJAVAファイルはextends DBTestCaseを追加したらDBUnitのファクションが使用できます。例:
class ABTest extends DBTestCase {}

DbUnitには、XMLデータセットとの間でデータベースデータをエクスポートおよびインポートする機能があります。

最初はDBに接続が必要ですね。
        String jdbcUrl = "jdbc:mariadb://127.0.0.1:36/database_test?useUnicode=true&useLegacyDatetimeCode=false";
        Connection jdbcConnection = DriverManager.getConnection(jdbcUrl, "root", "password_of_root");
        IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
上記の3行で接続完了。

次に、DBをバックアップの時backup.xmlにエクスポート。例えばsettingsとtest_casesを出力したいなら
        IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
        QueryDataSet queryDataSet = new QueryDataSet(connection);
        queryDataSet.addTable("settings", "SELECT * FROM settings");
        queryDataSet.addTable("test_cases", "SELECT * FROM test_cases");
        FlatXmlDataSet.write(queryDataSet, new FileOutputStream("./backup.xml"));
上記のコードを実行すると、backup.xmlファイルが作成され、内容はだいたい以下になります。

3.2 テスト用データを追加

テスト用のデータを準備します。
以下はXMLの例のファイルです:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <settings id="1" name="テスト1" is_testing="true" created_at="2019-09-01 20:07:05.0" updated_at="2019-09-01 20:07:05.0"/>
  <settings id="2" name="テスト2" is_testing="true" created_at="2019-09-01 20:07:05.0" updated_at="2019-09-01 20:07:05.0"/>
 <test_cases id="1" setting="1" value="0" created_at="2019-09-01 20:07:05.0" updated_at="2019-09-01 20:07:05.0"/>
 <test_cases id="2" setting="2" value="0" created_at="2019-09-01 20:07:05.0" updated_at="2019-09-01 20:07:05.0"/>
</dataset>
で、早速ですが、JAVAでの旧データ削除して、準備したデータを追加します。
     IDataSetProducer producer = new FlatXmlProducer(new InputSource(testPath));
     DatabaseOperation.CLEAN_INSERT.execute(connection, new StreamingDataSet(producer));
     // CLEAN_INSERT実は以下の2つ作業を実施します。
        DatabaseOperation.DELETE_ALL.execute(connection, new StreamingDataSet(producer));
        DatabaseOperation.INSERT.execute(connection, new StreamingDataSet(producer));
上記行ったのは「CLEAN_INSERT実は以下の2つ作業を実施します。」ですが、実は下の二つ行のコードが妙に違います。

CLEAN_INSERTは1つのStreamingDataSetを作成したが、DELETE_ALLとINSERTに分けて実装したら2つのStreamingDataSetを作成しました。

もし、あなたは以下のエラーが発生しましたら、DELETE_ALLとINSERTに分けて実装して見てください。
java.lang.UnsupportedOperationException: Only one iterator allowed!

3.3 バックアップデータでDBを復旧する

復旧の方は単なるバックアップしたデータをDBにインサートします。
producer = new FlatXmlProducer(new InputSource("backup.xml"));
DatabaseOperation.INSERT.execute(connection, new StreamingDataSet(producer));

4. DBUnitの操作リストは以下になります。

操作 説明
DatabaseOperation.UPDATE update処理を行います。この操作を実行すると、引数で指定されたデータセットのように、テーブルを更新します。この操作はSQLのupdate文を実行します。よって、テーブルにはすでにIDataSetで表されるデータが登録されている必要があります。データが存在しない場合は、エラーになります。
DatabaseOperation.INSERT insert処理を行います。この操作を実行すると、引数で指定されたデータセットをテーブルに挿入します。この操作はSQLのinsert文を実行します。よって、テーブルに該当データがすでに存在する場合は、エラーになります。
DatabaseOperation.DELETE delete処理を行います。データセットで表されるデータをテーブルより削除します。
DatabaseOperation.DELETE_ALL データセットで示されているテーブルのすべてのデータを削除します。
DatabaseOperation.TRUNCATE データセット内で示されているテーブルそのものを削除します。
DatabaseOperation.REFRESH 文字通り、対象のデータベースを「リフレッシュ」します。既にデータが存在する場合はデータを更新し、存在しない場合は挿入します。テーブルに存在するがデータセットに含まれないデータは何も変化しません。
DatabaseOperation.CLEAN_INSERT DELETE_ALL処理を実行した後、 INSERT処理を実行します。

5. まとめ

テストが便利になれるためツールと拡張機能が多いですが、JAVAでのDBUnit実装が簡単で、データ管理やすい(XML形で使用)。

初めて、使用しても、上記の簡単な例を参考すればと思います。

最後に、次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。アプリケーション開発の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。

皆さんのご応募をお待ちしています。

 

 

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事