About

Core

プロジェクト文書

Built by Maven

Abstract

JUnit CDI Extensions Core は,JUnit4 で CDI を利用したテストを行うための基本機能を提供します.

テストクラスで CDI を利用するには, @RunWith アノテーションに org.seasar.junitcdi.core.runner.CDI クラスを指定します.

@RunWith(CDI.class)
public class XxxTest {
    ...
}

これにより,CDI コンテナが準備されます.

JUnit CDI Extensions では,テストクラス自体も CDI で管理されます. そのため,テストクラスの .class ファイルが作成されるディレクトリには META-INF/beans.xml ファイルが必要です.

Maven2 のディレクトリ構成であれば, src/test/resources/META-INF/beans.xml を作成します.

ファイルの内容は以下のようにルート要素だけで構いません. 詳細は CDI の仕様書を参照してください.

<bean></bean>

Injection

テストクラスも CDI で管理されるため,通常の bean と同じように @Inject アノテーションにより bean が注入されます.

@RunWith(CDI.class)
public class XxxTest {
    @Inject
    XxxBean xxx;
    ...
}

Contexts

JUnit CDI Extensions では,CDI 標準のコンテキスト (スコープ) を利用することができます.

  • @ApplicationScoped
  • @Session
  • @Scoped
  • @Singleton
  • @Default (デフォルト)

いずれのコンテキストもテストメソッドを実行している間だけ有効で, テストメソッドの実行が終了するとコンテキストはクリアされます.

TestClassScoped

JUnit CDI Extensions は,同じテストクラスの複数のメソッドを実行している間有効な, 独自の「テストクラス・スコープ」を提供します.

「テストクラス・スコープ」を使うには,bean に org.seasar.junitcdi.core.TestClassScoped アノテーションを指定します.

以下の例では,テストメソッド hoge() および moge() の実行時,フィールド xxx には同じ bean が注入されます.

@TestClassScoped
public class XxxBean {
    ...
}

@RunWith(CDI.class)
public class XxxTest {
    @Inject
    XxxBean xxx;

    @Test
    public void hoge() {
        ...
    }

    @Test
    public void moge() {
        ...
    }
    ...
}

テストクラスをまたがったスコープは提供されません.

Lifecycle Methods

JUnit4 Lifecycle Methods

JUnit CDI Extensions は,JUnit4 標準のライフサイクルメソッドに加えて, 特定のテストメソッドの前後に呼び出されるライフサイクルメソッドを提供します.

特定のテストメソッドの前に呼び出されるメソッドには, org.seasar.junitcdi.core.BeforeMethod アノテーションを,後に呼び出されるメソッドには org.seasar.junitcdi.core.AfterMethod を指定します.

以下の例では, beforeHoge() メソッドは hoge() メソッドが実行される前に, afterHoge() メソッドは hoge() メソッドが実行された後に呼び出されます.

@RunWith(CDI.class)
public class XxxTest {
    @BeforeMethod
    public void beforeFoo() {
        ...
    }
    @Test
    public void foo() {
        ...
    }
    @AfterMethod
    public void afterFoo() {
        ...
    }
    ...
}

デフォルトでは,ライフサイクルメソッドの名前から before/after を取り除いて先頭を小文字にした名前のテストメソッドが対象となります.

アノテーションで対象となるテストメソッドを (複数) 明示することも出来ます.

以下の例では, before() メソッドは hoge() および moge() メソッドが実行される前に呼び出されます.

@RunWith(CDI.class)
public class XxxTest {
    @BeforeMethod({"hoge", "moge"})
    public void before() {
        ...
    }
    @Test
    public void hoge() {
        ...
    }
    @Test
    public void moge() {
        ...
    }
    ...
}

CDI Lifecycle Methods

テストクラスも CDI で管理されるため,通常の bean と同じように CDI のライフサイクルメソッドを持つことが出来ます.

以下の例では,テストクラスのインスタンスが作成されて DI が終了した後に hoge() メソッドが,テストが終了してテストクラスのインスタンスが破棄される際に moge() メソッドが呼び出されます.

@RunWith(CDI.class)
public class XxxTest {
    @PostConstruct
    public void hoge() {
        ...
    }
    @PreDestroy
    public void moge() {
        ...
    }
    ...
}

Events

JUnitの org.junit.runner.notification.RunListener による通知を,CDI のイベントとして任意の bean で受信することが出来ます.

public class XxxBean {
    public void onTestStarted(@Observes @TestStarted Description description) {
        ...
    }
    ...
}

サポートされる通知と対応するアノテーションおよびパラメータの型は以下の通りです.

JUnitの通知 アノテーション イベントの型
testStarted(Description) org.seasar.junitcdi.core.event.TestStarted org.junit.runner.Description
testFinished(Description) org.seasar.junitcdi.core.event.TestFinished org.junit.runner.Description
testFailure(Failure) org.seasar.junitcdi.core.event.TestFailure org.junit.runner.notification.Failure
testAssumptionFailure(Failure) org.seasar.junitcdi.core.event.TestAssumptionFailure org.junit.runner.notification.Failure
testIgnored(Description) org.seasar.junitcdi.core.event.TestIgnored org.junit.runner.Description

testRunStarted(Description) および testRunFinished(Result) はサポートされません.

JUnit CDI Extensions 独自のイベントもあります. イベントの型はいずれも org.seasar.junitcdi.core.event.TestInfo です.

アノテーション イベントが発生するタイミング
org.seasar.junitcdi.core.event.TestMethodStarted テストメソッドが呼び出される直前
org.seasar.junitcdi.core.event.TestMethodFinished テストメソッドが呼び出された直後

以下の例では,テストメソッドが呼び出される直前に onTestMethodStarted() メソッドが呼び出されます.

public class XxxBean {
    public void onTestMethodStarted(@Observes @TestMethodStarted TestInfo testInfo) {
        ...
    }
    ...
}

テストメソッドに Qualifier が指定されると,それがイベントにも反映されます.

以下の例では, hoge() メソッドのように @Hoge で注釈されたテストが実行される前にだけ XxxBean クラスの onHogeStarted() メソッドが呼び出されます.

@Qualifier
@Target( { METHOD, PARAMETER })
@Retention(RUNTIME)
public @interface Hoge {
}

@RunWith(CDI.class)
public class XxxTest {
    @Test
    @Hoge
    public void hoge() {
        ...
    }
    ...
}

public class XxxBean {
    public void onHogeStarted(@Observes @TestStarted @Hoge Description description) {
        ...
    }
    ...
}

テストが正常に実行される際の, ライフサイクルメソッドおよび, RunListener イベントと JUnit CDI Extensions 独自のイベントが発生する順序関係は以下のようになります.

ライフサイクルメソッド RunListener イベント 独自イベント
@BeforeClass
@TestStarted
@Before
@BeforeMethod
@TestMethodStarted
@Test
@TestMethodFinished
@AfterMethod
@After
@TestFinished
@AfterClass

JNDI

JUnit CDI Extensions は,JNDI 経由で CDI コンテナから bean をルックアップする javax.naming.Context を提供します.

これにより,JNDI でルックアップされるコンポーネントや @Resource アノテーションで DI されるコンポーネントを bean として用意しておくこくことができます.

この JNDI Context を利用するには,クラスパスに jndi.properties ファイルを作成して以下の内容を記述します.

java.naming.factory.initial=org.seasar.junitcdi.core.internal.JndiContextFactory

これで InitialContext を利用して CDI コンテナから bean をルックアップすることができます.

DataSource ds = InitialContext.doLookup("java:comp/env/jdbc/DataSource");

あるいは,上記の内容をもった Hashtable を作成して InitialContext を作成します.

Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.seasar.junitcdi.core.internal.JndiContextFactory");
Context ctx = new InitialContext(env);
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/DataSource");