DBUnitを使って、XMLから読み込んだデータをテーブルに挿入し、期待値と比較する。Mavenのpom.xmlも最後に記載。


スポンサーリンク

DBUnitはJUnitを拡張したライブラリです。
データベースの参照や更新を行うクラスに対してユニットテストを行うことができます。
DBが更新されてしまうと、ユニットテストの結果が変わってしまい、テストが行いにくいという問題があります。
DBUnitを使用すると、テストを実行する前にテストデータをDBに投入したり、テスト後に初期化することなどができます。

今回はDBUnitを使って、テーブルに初期化データを入れて、テストをしてみます。
対象となるテーブルを作ってみます。

mysql> create table member(id char(5) primary key, name varchar(20), birth date);
Query OK, 0 rows affected (0.03 sec)

mysql> select * from member;
Empty set (0.00 sec)

このテーブルに対して、DBUnitを使ってテストをしてみます。
まず、テストデータなんですけど、初期投入データがこちら。

init.xml

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <member id="0001" name="taro" birth="1990-10-10"/>
  <member id="0002" name="hanako" birth="1985-02-22"/>
  <member id="0003" name="sayaka" birth="1991-03-10"/>
</dataset>

で、テーブルの期待する値を書いたXMLがこちら。
expected.xml

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <member id="0001" name="taro" birth="1990-10-10"/>
  <member id="0002" name="hanako" birth="1985-02-22"/>
  <member id="0003" name="sayaka" birth="1991-03-10"/>
</dataset>

もうひとつ。初期データに一つデータを挿入して、その期待値を見るパターン。

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <member id="0001" name="taro" birth="1990-10-10"/>
  <member id="0002" name="hanako" birth="1985-02-22"/>
  <member id="0003" name="sayaka" birth="1991-03-10"/>
  <member id="0004" name="yuka" birth="1990-05-10"/>
</dataset>
package example.unittest;

import java.io.File;
import java.sql.Connection;
import java.sql.Statement;

import org.dbunit.Assertion;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


public class DBUnitTest{

	private IDatabaseTester databaseTester;
	private IDatabaseConnection connection;

	public DBUnitTest() throws Exception {
		//テストクラスをインスタンス化するときに、DBに接続するためのtesterを作成する
		databaseTester = new JdbcDatabaseTester("com.mysql.jdbc.Driver","jdbc:mysql://localhost/sample", "sample", "1234");
	}

	@Before
	public void before() throws Exception {
		//テーブルに初期化用のデータを投入する
		IDataSet dataSet =
				new FlatXmlDataSetBuilder().build(new File("data/init.xml"));
		databaseTester.setDataSet(dataSet);
		databaseTester.setSetUpOperation(DatabaseOperation.REFRESH);

		databaseTester.onSetup();
	}

	@After
	public void after() throws Exception {
		databaseTester.setTearDownOperation(DatabaseOperation.NONE);
		databaseTester.onTearDown();
	}

	@Test
	public void compareTable() throws Exception {
		IDataSet databaseDataSet = databaseTester.getConnection().createDataSet();
		ITable actualTable = databaseDataSet.getTable("member");

		IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File("data/expected.xml"));
		ITable expectedTable = expectedDataSet.getTable("member");

		Assertion.assertEquals(expectedTable, actualTable);
	}

	@Test
	public void insertTable() throws Exception {
		IDatabaseConnection testerConnection = databaseTester.getConnection();
		Connection con = testerConnection.getConnection();
		IDataSet databaseDataSet = databaseTester.getConnection().createDataSet();

		Statement stmt = con.createStatement();
		stmt.executeUpdate("insert into member(id,name,birth) values('0004','yuka','1990-05-10')");

		ITable actualTable = databaseDataSet.getTable("member");
		IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File("data/expected2.xml"));
		ITable expectedTable = expectedDataSet.getTable("member");

	}


}

ちょっと解説すると、最初のcompareTableというテストは、初期データを投入して、それがexpected.xmlと同じ値になっているかを見ています。
実際のテーブルはこんな感じのデータが入るわけです。

mysql> select * from member;
+------+--------+------------+
| id   | name   | birth      |
+------+--------+------------+
| 0001 | taro   | 1990-10-10 |
| 0002 | hanako | 1985-02-22 |
| 0003 | sayaka | 1991-03-10 |
+------+--------+------------+

次の、insertTableのテストは、初期データに加えて一つデータをinsertしてみます。
その結果が、expected2.xmlと等しいことを確認します。

実際のテストを行ったときのテーブルの状態は以下のようになります。

mysql> select * from member;
+------+--------+------------+
| id   | name   | birth      |
+------+--------+------------+
| 0001 | taro   | 1990-10-10 |
| 0002 | hanako | 1985-02-22 |
| 0003 | sayaka | 1991-03-10 |
| 0004 | yuka   | 1990-05-10 |
+------+--------+------------+

あと、

databaseTester.setSetUpOperation(DatabaseOperation.REFRESH);

というREFRESHみたいなことをやっていますが、以下のようなことをするようです。

 * This operation literally refreshes dataset contents into the database. This
 * means that data of existing rows is updated and non-existing row get
 * inserted. Any rows which exist in the database but not in dataset stay
 * unaffected.

無いデータを入れて、存在するデータはupdateする。

REFRESHの他にも、DELETEやUPDATEがあるようです。

public static final DatabaseOperation NONE = new DummyOperation();
public static final DatabaseOperation UPDATE = new UpdateOperation();
public static final DatabaseOperation INSERT = new InsertOperation();
public static final DatabaseOperation REFRESH = new RefreshOperation();
public static final DatabaseOperation DELETE = new DeleteOperation();
public static final DatabaseOperation DELETE_ALL = new DeleteAllOperation();
public static final DatabaseOperation TRUNCATE_TABLE = new TruncateTableOperation();
public static final DatabaseOperation CLEAN_INSERT = new CompositeOperation(
        DELETE_ALL, INSERT);   


今回のDBUnitを実行するためのMaven2のpom.xmlは以下のとおり。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>unittest</groupId>
  <artifactId>unittest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>unittest</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.4</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>1.7.7</version>
	</dependency>
	<dependency>
		<groupId>commons-collections</groupId>
		<artifactId>commons-collections</artifactId>
		<version>3.2.1</version>
	</dependency>
	<dependency>
		<groupId>org.dbunit</groupId>
		<artifactId>dbunit</artifactId>
		<version>2.4.8</version>
	</dependency>

	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi</artifactId>
		<version>3.11-beta3</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.6</version>
	</dependency>



  </dependencies>
</project>

f:id:sho322:20141211021310j:plain

次は、Excelからデータを読み込んでテストするっていうのをやってみます。

以下の本に詳しいサンプルが載っています。

現場で使えるJavaライブラリ

現場で使えるJavaライブラリ