Develop with pleasure!

福岡でCloudとかBlockchainとか。

Springで単体テスト

SpringFrameworkをベースに開発をしてるということは、テスト時も必要な個所は(DataSourceのインジェクションや、ORM使ってたらiBATISの場合は、SqlMapClientのインジェクション)ApplicationContextの設定を引き継いだ状態でテストをしたい。Springでは予めapplicationContext.xmlを読み込んでくれるサポートクラスが存在する。

例えばDAOのテストケースであれば、AbstractTransactionalDataSourceSpringContextTestsといったクラスが提供される。また、applicationContext.xmlを読み込むよう、org.springframework.test.context.ContextConfigurationというアノテーションが用意されている。
AbstractTransactionalDataSourceSpringContextTestsを継承したテストケースを作成し、そのクラス宣言に@ContextConfigurationを付加すれば、テストケースを実行する際に、テストケースと同じパッケージ上に存在する「テストケースのクラス名-context.xml」が読み込まれるようになる。また、別の場所にあるapplicationContext.xmlを読み込む場合は、@ContextConfigurationにlocationを指定すれば良い。

こんな感じ

package org.hoge.dao;

import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.junit.runner.RunWith;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
		locations = {"/applicationContext.xml", "/applicationContext-dao.xml"})
public class AbstractDaoTestCase extends AbstractTransactionalDataSourceSpringContextTests {
}

@ContextConfigurationアノテーションは、@Inheritedアノテーションを定義しているアノテーションになるため、サブクラスにもアノテーションの定義内容が継承される。そのため共通で使用するapplicationContext.xmlを読み込むAbstractDaoTestCaseのようなものクラスを用意して、個別のテストケース毎にテスト用のapplicationContext.xmlを読み込ませたい場合にのみサブクラスで@ContextConfigurationを定義するといった使い方が良さげだ。

あとはテスト対象のオブジェクトをSpringにインジェクションさせるにはテストケースのフィールドとして対象のオブジェクトを定義し、@Autowiredアノテーションを付加すれば良い。Springに依存することなく、JSR-250に従うのであれば、@Resourceアノテーションを利用する。

import javax.annotation.Resource;
...
    @Resource
    private HogeEntityDao hogeEntityDao;

としておけば、hogeEntityDaoというIDでBean定義されたクラスのオブジェクトがインジェクションされるので、あとは各テストメソッドでそれらを利用してテストコードを書けば良い。