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ライブラリを使うために追加してます。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | < 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メソッド
01 02 03 04 05 06 07 08 09 10 11 12 13 | 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
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | @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がうまく動いてくれないらしい・・・
1 2 3 4 5 6 7 | < 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
セットアップ用のデータです。
1 2 3 4 5 6 | <? 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”に変更しています。
1 2 3 4 5 6 | <? 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
コメントを書く