- 1. Spring FrameworkのUnitテスト実装方法 1-3.Repositoryテスト(Junit4, spring-test, DBUnit)
- 2. 1-3.Repositoryテスト Junit4,Spring-test,DBUnitライブラリを使用したパターン
Spring FrameworkのUnitテスト実装方法 1-3.Repositoryテスト(Junit4, spring-test, DBUnit)
TERASOLUNA Server Framework for Java (5.x) Development Guideline
サンプルソースはこちら
(これのMyBatis3を使用したパターンで作成してます。)
1-3.Repositoryテスト Junit4,Spring-test,DBUnitライブラリを使用したパターン
セットアップを簡単にするために、DBUnitを使ってxmlファイルからデータのセットアップを行います。
【pom.xml】
DBUnitライブラリを使うために追加してます。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.5.4</version>
<scope>test</scope>
</dependency>
</dependencies>
【テスト対象クラス】
TodoRepository.java
テスト対象はupdateメソッド
public interface TodoRepository {
Todo findOne(String todoId);
Collection<Todo> findAll();
void create(Todo todo);
boolean update(Todo todo);
void delete(Todo todo);
long countByFinished(boolean finished);
}
【テストクラス】
TodoRepositoryTestVerDBunit.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:META-INF/spring/test-context-dbunit.xml"})
@Transactional
public class TodoRepositoryTestVerDBunit extends DataSourceBasedDBTestCase {
private final String RESOURCE_DIR = "src/test/resources/META-INF/dbunit/";
@Inject
TodoRepository target;
@Inject
JdbcTemplate jdbctemplate;
@Inject
private TransactionAwareDataSourceProxy dataSourceTest;
@Before
public void setUp() throws Exception {
super.setUp();
/* 意味ないかもしれないけど、ここで実行することでファイルとDBの格納後の整合性確認ができる。
IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("todo");
IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File(RESOURCE_DIR + "test_data.xml"));
ITable expectedTable = expectedDataSet.getTable("todo");
Assertion.assertEquals(expectedTable, actualTable);
*/
}
@Test
@Rollback
public void testUpdate() throws Exception {
//テスト用のデータを作成(getTodoDataメソッドはDBからデータを取得するprivateメソッド。取得したデータを書き換えて更新する。)
String todoId = "cceae402-c5b1-440f-bae2-7bee19dc17fb";
Todo testDataTodo = getTodoData(todoId);
testDataTodo.setFinished(true);
//updateメソッドのテスト
boolean actTodo = target.update(testDataTodo);
//結果検証
assertEquals(actTodo, true);
//メソッド実行後テーブルデータ検証
//ここで指定したxmlファイルには、テスト対象のメソッド実行後に更新されたテーブルの内容の期待値を記述している
Assertion.assertEquals(getexpectedTable(RESOURCE_DIR + "compare_data.xml"), getactualTable());
}
//テーブルからデータを取得
private ITable getactualTable() throws Exception {
IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("todo");
return actualTable;
}
//期待値となるデータをファイルから取得するメソッド。引数はファイルのパス
private ITable getexpectedTable(String filepath) throws Exception {
IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File(filepath));
ITable expectedTable = expectedDataSet.getTable("todo");
return expectedTable;
}
//DBunitを使用するためのオーバーライド
@Override
protected DataSource getDataSource() {
// TODO 自動生成されたメソッド・スタブ
return dataSourceTest;
}
//DBunitを使用するためのオーバーライド
@Override
protected IDataSet getDataSet() throws Exception {
// TODO 自動生成されたメソッド・スタブ
return new FlatXmlDataSetBuilder().build(new FileInputStream(RESOURCE_DIR + "test_data.xml"));
}
}
DBUnitの処理について、xmlファイルを読み込むようにメソッドをオーバーライドしてます。
【その他設定】
test-context-dbunit.xml
DBunitを有効にするために少しtest-context.xml(1-1参照)を書き換えてます。
これをしないとDBunitがうまく動いてくれないらしい・・・
<bean id="log4jDataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
<constructor-arg index="0" ref="realDataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg index="0" ref="log4jDataSource" />
</bean>
test_data.xml
セットアップ用のデータです。
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<TODO TODO_ID="cceae402-c5b1-440f-bae2-7bee19dc17fb" TODO_TITLE="one" FINISHED="false" CREATED_AT="2017-10-01 15:39:17.888" />
<TODO TODO_ID="5dd4ba78-ff5b-423b-aa2a-a07118aeaf90" TODO_TITLE="two" FINISHED="false" CREATED_AT="2017-10-01 15:39:19.981" />
<TODO TODO_ID="e3bdb9af-3dde-40b7-b5fb-4b388567ab45" TODO_TITLE="three" FINISHED="false" CREATED_AT="2017-10-01 15:39:28.437" />
</dataset>
compare_data.xml
テストメソッド実行後の検証用データです。
テストメソッドの内容が、ID”cceae402-c5b1-440f-bae2-7bee19dc17fb”のデータに対してFinishedをtrueにする内容なので、
test_data.xmlの内容からID=”cceae402-c5b1-440f-bae2-7bee19dc17fb”のFINISHEDを”true”に変更しています。
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<TODO TODO_ID="5dd4ba78-ff5b-423b-aa2a-a07118aeaf90" TODO_TITLE="two" FINISHED="false" CREATED_AT="2017-10-01 15:39:19.981" />
<TODO TODO_ID="cceae402-c5b1-440f-bae2-7bee19dc17fb" TODO_TITLE="one" FINISHED="true" CREATED_AT="2017-10-01 15:39:17.888" />
<TODO TODO_ID="e3bdb9af-3dde-40b7-b5fb-4b388567ab45" TODO_TITLE="three" FINISHED="false" CREATED_AT="2017-10-01 15:39:28.437" />
</dataset>
xmlでどんどんデータを書いていけばいいので、大量データのセットアップとかも含めてやっぱりDBUnitによるセットアップがおすすめですね。
データの検証もやってくれるし。
ちなみにテストメソッド実行後のテーブルデータと、compare_data.xmlの内容が異なっていた場合、
Junit上でエラーになります。(例のバーが赤くなる)
ちょっと面倒なのが、compare_data.xmlの中のデータの順番まで合わせなきゃいけないことです。。。
自分がやった限りでは更新後のテーブルの順番にちゃんと合わせないとエラーになるのですが、
データの整合性だけ見てくれるように設定とかできないのですかね・・・
サンプルソースはgithubで公開してます。
Spring-Unit-Test-pattern3