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

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

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

備忘録かねてSpring FrameworkのUnitテストの実装方法をパターン別にまとめていきます。

元のサンプルはTERASOLUNA Frameworkのチュートリアルサンプルを使用しています。
TERASOLUNAというNTTデータが作ったOSSですが、実際はほとんどSpring Frameworkになってます。
Spring Frameworkの最初の勉強用としては使えるかもしれません。
TERASOLUNA Server Framework for Java (5.x) Development Guideline
サンプルソースはこちら
(これのMyBatis3を使用したパターンで作成してます。)

ではいきます。

1-1.Repositoryテスト Junit4,Spring-testライブラリを使用したパターン

・DBへデータのセットアップ
・テスト用データの作成
・メソッドのテスト
・結果の検証
・テスト実行後のDB状態の確認
の流れを実装します。

【pom.xml】

テストに必要なライブラリは以下

<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>
</dependencies>

spring-testはSpringの機能であるDIコンテナを有効にしたりします。

本来であれば、Repository用のインタフェースに対してimplementした実装クラスを作成し、そこでDBへの接続とか色々していくのですが、
mybatisの場合インタフェースとそれに紐づいたsql文が書かれたxmlがあれば実装クラスを作成する必要がないです。
ということで、実装クラスが存在しないのでインタフェースを使って間接的にRepositoryのテストをしていくことになります。
そのため、Spring-testを使ってインタフェースを媒介にしてDIコンテナから自動で作成される実装クラスを引っ張り出す感じですね。

【テスト対象クラス】

TodoRepository.java

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);
}

今回はこの中のupdateメソッドについてテストコードを作っていこうと思います。

【テストクラス】

TodoRepositoryTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:META-INF/spring/test-context.xml"})
@Transactional
public class TodoRepositoryTest {

    @Inject
    TodoRepository target;
    
    @Inject
    JdbcTemplate jdbctemplate;
    
    @Before
    public void setUp() throws Exception {
        
        //JdbcTemplateでテーブルデータを初期化する
        jdbctemplate.update("DELETE FROM todo");
        
        //テーブルにデータをセットアップする(setUpTabledataメソッドはデータ作成用privateメソッド)
        List<Todo> todoList = setUpTabledata();
        for(int i=0; i < todoList.size(); i++) {
            Todo todo = todoList.get(i);
            //JdbcTemplateでセットアップ
            jdbctemplate.update("INSERT INTO todo (todo_id,todo_title,finished,created_at) VALUES(?,?,?,?)"
                    ,todo.getTodoId()
                    ,todo.getTodoTitle()
                    ,todo.isFinished()
                    ,todo.getCreatedAt()
                    );
        }
    }
    
    @Test
    @Rollback
    public void testUpdate() throws Exception {
        //テスト用のデータを作成
        SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String todoId = "cceae402-c5b1-440f-bae2-7bee19dc17fb";
        Todo testDataTodo = getTodoData(todoId);
        testDataTodo.setFinished(true);
        
        //updateメソッドのテスト
        boolean actTodo = target.update(testDataTodo);

        //結果検証
        assertEquals(actTodo, true);
        
        //期待値の作成
        Todo exptodo = new Todo();
        exptodo.setTodoId("cceae402-c5b1-440f-bae2-7bee19dc17fb");
        exptodo.setTodoTitle("one");
        exptodo.setFinished(true);
        String strDate = "2017-10-01 15:39:17.888";
        Date date = sdFormat.parse(strDate);
        exptodo.setCreatedAt(date);
        
        //処理後データの取得(getTodoDataメソッドはDBからテスト後に変更されたデータを取得するprivateメソッド)
        Todo actTestDataTodo = getTodoData(todoId);
        
        //メソッド実行後テーブルデータ検証
        //date型の表示形式が異なるため、時刻文字列に変換して比較している
        assertEquals(exptodo.getTodoId(), actTestDataTodo.getTodoId());
        assertEquals(exptodo.getTodoTitle(), actTestDataTodo.getTodoTitle());
        assertEquals(exptodo.isFinished(), actTestDataTodo.isFinished());
        assertEquals(sdFormat.format(exptodo.getCreatedAt()) ,sdFormat.format(actTestDataTodo.getCreatedAt()));
    }
}

【その他設定】

test-context.xml
JdbcTemplateを使えるように設定します。
基本はapplicationContext.xmlの設定を丸パクリして、不必要なものを削った感じです。

<!-- jdbcTemplateの設定 -->
<bean class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource" />
</bean>

JDBCTemplateを使ったシンプルなテストコードです。
ただ、テスト用のデータを大量に作成するとか、DBのセットアップが複雑な感じになる場合はテストコードの可読性が落ちそうですね。
できるならDbunitとか使った方がいいです。

サンプルソースはgithubで公開してます。
Spring-Unit-Test-pattern1

Junitカテゴリの最新記事