JavaでDBUnitというライブラリを使い、実際にDBと通信を行うテストを行う方法を説明します。
テーブルの構成
テストで使うDBは以下の通りとします。
- DB名...test
- テーブル名...animal
mysql> desc animal; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(100) | YES | | NULL | | +-------+--------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
テーブルにデータは入っていません。
テストコード
このテーブルにレコードを追加し、レコードが追加されたかどうか確認する、という内容です。
テストコード中で使うinsert.xlsxとexpected.xlsxは以下のような内容です。
insert.xlsxの内容をanimalテーブルに挿入し、その結果がexpected.xlsxと同じようになっているかを確認します。
また、xlsxファイルにおけるシート名はDBにおけるテーブル名と同じにする必要があります。
import org.dbunit.database.DatabaseConfig; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.excel.XlsDataSet; import org.dbunit.ext.mysql.MySqlMetadataHandler; import org.dbunit.operation.DatabaseOperation; import org.junit.Test; import static org.dbunit.Assertion.assertEquals; import java.io.File; import java.sql.Connection; import java.sql.DriverManager; public class InsertTest { String url = "jdbc:mysql://localhost:3306"; String user = "testUser"; String password = "testPass"; @Test public void insertTest() throws Exception { Connection conn = DriverManager.getConnection(url, user, password); IDatabaseConnection dbconn = new DatabaseConnection(conn, "test"); DatabaseConfig config = dbconn.getConfig(); config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler()); IDataSet dataset = new XlsDataSet(new File("data/insert.xlsx")); DatabaseOperation.CLEAN_INSERT.execute(dbconn, dataset); IDataSet expectedDataSet = new XlsDataSet(new File("data/expected.xlsx")); ITable expectedTable = expectedDataSet.getTable("animal"); IDataSet actualDataSet = dbconn.createDataSet(); ITable actualTable = actualDataSet.getTable("animal"); assertEquals(expectedTable, actualTable); } }
エラーが発生しがちなポイント
このテストコードの実装に際して、何箇所かエラーが発生して解決に時間を使ってしまったので、メモしておきます。
ファイルがないというエラーが出る
このエラーが出る場合は
new File(ファイル名)
としているところで、ファイル名に絶対パスを指定してください。
NoSuchColumnExceptionというエラーが出る
org.dbunit.dataset.NoSuchColumnException: animal.ID - (Non-uppercase input column: ID) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
というエラーが発生し、解決に時間を取られました。
こちらは、以下の2行を追加することにより解決しました。
DatabaseConfig config = dbconn.getConfig(); config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());
assertEquals()でエラー
assertEquals()というメソッドはDBUnitではなくJUnitの方にも存在しています。
またその双方でオーバーロードされており、assertEquals()というメソッドが大量に存在します。
assertEquals()のところでエラーになる場合、間違ったassertEquals()メソッドを使っていないか確かめてみてください。
補足
通常DBUnitテストを行う場合、@Beforeアノテーションを付与したメソッドで現在DBにあるデータを退避させ、テスト終了後は@Afterアノテーションを付与したメソッドで退避させたデータをもとに戻す、という処理を行います。
今回はDBUnitの基本的な使い方を説明したかったので省きましたが、この方法は調べればすぐに出てくると思います。
また、
DatabaseOperation.CLEAN_INSERT.execute(dbconn, dataset);
としている箇所ではCLEAN_INSERTの代わりにINSERTを使えます。INSERTを使った場合は、animalテーブル上のデータは消去されませんが、CLEAN_INSERTを使うと、animalテーブルのデータが全て消去されてからデータが挿入されます。