Spring FrameworkのUnitテスト実装方法 1-3.Repositoryテスト(Junit4, spring-test, DBUnit)

Spring FrameworkのUnitテスト実装方法 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ライブラリを使うために追加してます。

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

DBunitカテゴリの最新記事