理系学生日記

おまえはいつまで学生気分なのか

DBUnit でカラム値の比較をカスタマイズする

DBUnit の思想について - 理系学生日記 の記事の続きです。

DBUnit では、基本的にデータセット単位、あるいはテーブル単位で比較するので、このカラムの値がこういうときにはテストを OK としたい、というようなカラム値単位でのテスト制御を行うためにはちょっと頭を捻らなければなりません。 どういうケースかというと、例えば + テーブルに「更新日時」や「登録日時」を持っていて、必ず現在日時がセットされてしまう (Oracle の sysdate や、MySQL の now() など) + auto increment な主キーを持っていて、実際に insert するときまでその値が予測できない + auto increment な主キーに対して外部キーを張っていて、外部キーのカラムにどんな値が入るかはテスト時まで予想できない + 特定のカラムに対しては、完全一致 (equals) ではなく、数値の採る範囲で Assert させたい などです。

こういったケースで使用するのは、http://dbunit.sourceforge.net/apidocs/org/dbunit/assertion/DiffCollectingFailureHandler.html で、これよりもっとカスタマイズしたい場合は、DifferenceListener や FailureHandler を実装したクラスを自分で作ることになります。

使い方については、DBUnit にしては珍しく、JavaDoc でコードが記述されています。引用すると以下の通り。

|java| IDataSet dataSet = getDataSet(); DiffCollectingFailureHandler myHandler = new DiffCollectingFailureHandler(); //invoke the assertion with the custom handler assertion.assertEquals(dataSet.getTable("TEST_TABLE"), dataSet.getTable("TEST_TABLE_WITH_WRONG_VALUE"), myHandler); // Evaluate the results List diffList = myHandler.getDiffList(); Difference diff = (Difference)diffList.get(0); ||<

Assert するときに Diffcollectingfailurehandler のオブジェクトを渡せば、そのオブジェクトが、差分のあったカラム情報を Difference のリストとして収集してくれます。 あとは、このリストを取得していけば、差分に対してどう対処するかをコードとして記述することができます。

*** 注意点 差分の定義は、あくまでカラム値の違いです。そもそも、比較対象の 2 つのテーブルが持っているレコード数が異なる、といった場合、assertEquals は容赦なく失敗します。

** Difference オブジェクトの使い方

Difference オブジェクトから (間接的に)取れる情報は多岐に渡りますが、重要なのは以下だと思います。 - 差分があったテーブル名 -- Difference オブジェクトを d としたとき、

|java| d.getActualTable().getTableMetaData().getTableName() (d.getExpectedTable() でも取れる) ||< - 差分があったカラム名 - 期待値 - 実際の値

これらの値が取れれば、特定テーブル、カラムのときは、こういう Assert をしたい、というような粒度で比較を行うことが (コードを書けば) できるようになります