S2Unitを使ってログイン検証インターセプタを単体テスト

Seasar2には、S2Unitという単体テスト支援ツールが含まれている。ツールと言っても、いわゆるJUnitみたいなもので、実際、S2UnitはJUnitを拡張して作られている。今回は、昨日の記事に書いたログイン検証インターセプタのテストをS2Unitで行う方法を書こうと思う。

テスト観点

  • クラスに@Authenticationが定義されていて、@Executeがついているメソッドのみで検証処理が行われること
  • 検証対象のメソッドで、ログイン情報が存在しない場合は、ログイン画面に遷移するパスが返却されること
  • 検証対象のメソッドで、ログイン情報が存在する場合は、通常のメソッドがそのまま呼び出されること

テスト用のActionクラス

ログイン検証アノテーションが定義されているActionクラス。

@Authentication
public class TestActionAuth {

    @Execute
    public String execute() { // このメソッドが検証対象になる
        return null;
    }

    public String noExecute() {
        return null;
    }
}

ログイン検証アノテーションが定義されていないActionクラス。

// どのメソッドも検証処理は行われないはず
public class TestActionNotAuth {

    @Execute
    public String execute() {
        return null;
    }

    public String noExecute() {
        return null;
    }
}

単体テストクラス

S2TestCaseを継承した単体テストクラス。

public class AuthenticationInterceptorTest extends S2TestCase {

    private static final String PAHT = "authenticationInterceptorTest.dicon";

    private LoginDto loginDto;

    private TestActionAuth testActionAuth;

    private TestActionNotAuth testActionNotAuth;

    public void setUp() {
        include(PAHT);
    }

    public void test処理対象で未認証() {
        loginDto.id = null; // 未認証
        assertNotNull(testActionAuth.execute()); // 実際にはログイン画面に遷移するパスが返されるはず
    }

    public void test処理対象で認証済み() {
        loginDto.id = 1;    // 認証
        assertNull(testActionAuth.execute());    // 本来のアクションが実行されnullが返されるはず
    }

    public void test処理対象外_Authenticationがある_Executeがない() {
        loginDto.id = null; // 未認証
        assertNull(testActionAuth.noExecute());
    }

    public void test処理対象外_Authenticationがない_Executeがある() {
        loginDto.id = null; // 未認証
        assertNull(testActionNotAuth.execute());
    }

    public void test処理対象外_Authenticationがない_Executeがない() {
        loginDto.id = null; // 未認証
        assertNull(testActionNotAuth.noExecute());
    }
}

S2TestCaseでは、include()を呼び出すことでdiconファイルが読み込まれ、S2Containerが初期化される。diconファイルに定義されたコンポーネント名と同じフィールドが定義されていれば、自動的にセットしてくれる。

  • ログイン情報を変更できるようにLoginDtoをフィールドに用意
  • setUp()内でdiconファイルを読み込み

diconファイル

単体テストクラスで使用するコンポーネントを定義したdiconファイル。

<components>
	<component name="loginDto" class="levelup.dto.LoginDto" />
	<component name="authenticationInterceptor" class="levelup.aop.AuthenticationInterceptor" />
	<component class="levelup.aop.TestActionAuth">
		<aspect>authenticationInterceptor</aspect>
	</component>
	<component class="levelup.aop.TestActionNotAuth">
		<aspect>authenticationInterceptor</aspect>
	</component>
</components>
  • ログイン情報としてLoginDtoを定義
  • ログイン検証用インターセプタを定義
  • テスト用の2つのActionクラスを定義し、ログイン検証用インターセプタをアスペクトとして登録

テストの実行

S2TestCaseはJUnitのTestCaseを継承したクラスなので、普通にJUnitのテストケースとしてテストを実行できる。

はい、オールグリーン。

S2Unit感想

  • DIコンテナの機能を利用したインターセプタのテストも自動化できてGood!
  • diconファイルを書くのは少し手間
  • DIコンテナの初期化に時間がかかるため、通常のJUnitテストケースよりはテストの実行に時間がかかる

手間やテスト実行時間を考えると、DIコンテナの機能を使わなければテスト出来ない(あるいはしにくい)場合を除いて、通常のJUnitテストケースを利用したほうが良いかも。ケースバイケース。