Spring FrameworkのUnitテスト実装方法 1-1.Repositoryテスト(Junit4, spring-test)
備忘録かねてSpring FrameworkのUnitテストの実装方法をパターン別にまとめていきます。
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】
テストに必要なライブラリは以下
01 02 03 04 05 06 07 08 09 10 11 12 13 | < 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
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); } |
今回はこの中のupdateメソッドについてテストコードを作っていこうと思います。
【テストクラス】
TodoRepositoryTest.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 | @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の設定を丸パクリして、不必要なものを削った感じです。
1 2 3 4 | <!-- jdbcTemplateの設定 --> < bean class = "org.springframework.jdbc.core.JdbcTemplate" > < constructor-arg ref = "dataSource" /> </ bean > |
JDBCTemplateを使ったシンプルなテストコードです。
ただ、テスト用のデータを大量に作成するとか、DBのセットアップが複雑な感じになる場合はテストコードの可読性が落ちそうですね。
できるならDbunitとか使った方がいいです。
サンプルソースはgithubで公開してます。
Spring-Unit-Test-pattern1
コメントを書く