S2JDBCでDBを使わずにユニットテストする

以前、MockRunnerのJDBCMockを使ってDBを使わずにSQLを文字列比較することでDAOのユニットテストを行う方法について書きました。

今やってるプロジェクトではS2JDBCを使っているのですがMockRunnerだけだと特に戻り値の設定が面倒だったため、戻り値の設定部分のみJdbcManagerのモックを使用しています。これをS2JDBCのレイヤだけで行えるようにするモックを作成してみました。ソースは以下のSVNリポジトリにあります。

設定ではユニットテスト用のs2jdbc.diconでJdbcManagerを定義している部分をorg.seasar.s2jdbcmock.MockJdbcManagerに変更するだけです。
テストケースではorg.seasar.s2jdbcmock.S2JdbcUnitのメンバをstaticインポートしてSQLの検証を行うことができます。以下はS2JUnit4を使用した場合のテストケースの例です。

package org.seasar.s2jdbcmock.service;

import static junit.framework.Assert.*;
import static org.seasar.s2jdbcmock.S2JdbcUnit.*;

...

@RunWith(Seasar2.class)
public class EmployeeServiceTest {

  protected EmployeeService sampleService;

  @Before
  public void init(){
    initS2JdbcUnit();
  }

  @Test
  public void testGetEmployeeTx(){
    // サービスのメソッドを実行
    sampleService.getEmployee(1);
    // 正規表現でSQLを検証
    verifySqlByRegExp(0, "SELECT .* FROM EMPLOYEE .* WHERE .*EMP_ID = \\?", 1);
  }

}

上記の例では正規表現で検証していますが、SQLは空白や改行、大文字小文字、コメントなどを適度に正規化して比較しているので、厳密に文字列として完全一致するように記述しなくても大丈夫です。
サービスクラスのメソッドによってはJdbcManagerの戻り値によって処理が分岐するようなケースもあるでしょう。そのような場合はS2JdbcUnit#addResult()メソッドでJdbcManagerが返却する値を設定することができます。MockJdbcManagerはSQLを実行するためにaddResult()された値を順番に返却します(INSERTやUPDATE時の更新件数も戻り値ですのでaddResult()で設定しておくことができます)。

  @Test
  public void testGetEmployeeTx(){
    // JdbcManagerの返却値を設定
    Employee result = new Employee();
    ...
    addResult(result);

    // サービスのメソッドを実行(上でセットしたエンティティが返却される)
    Employee employee = sampleService.getEmployeeList();
    ...
  }

まだバッチ更新系やストアド系には対応していませんが、今のプロジェクトで使っているMockRunner+自作JdbcManagerモックと比べると簡単に使えます。もちろんMockRunnerと違って使えるのはS2JDBCを使う場合に限られますが…。