UTFlute

DBFluteプロジェクトが提供するライブラリ UTFlute のページ。

UTFluteとは?

ずばり言うと

UTFlute は、自分で new したものにDIできる JUnit 拡張 です。

e.g. 自分で new した Action に DI だけして index() を実行 @Java
// ## Arrange ##
FooAction action = new FooAction();
inject(action);

// ## Act ##
action.index();

UTFluteの特徴

ざっとこんな感じです

inject()
自分で new したものに DI する
registerMockInstance()
inject()でDIされるコンポーネントをMockに
markHere()
ここを通ったことをassertするための仕組み (plain)
cannonball()
マルチスレッド実行、10スレッドでよーいドン! (plain)
projectA()
cannonball() の中で、手続き的にスレッドコントロール (plain)
policeStoryOf...()
JavaクラスやJSPファイルなどを走査して好きなようにチェック (plain)
readLine()
お手軽ファイル読み込み (テキストファイル) (plain)
テストクラスDI
テストクラスのフィールドにコンポーネントをDI
自動トランザクション
テストケースごとに強制Rollbackトランザクション
performNewTransaction()
独自にその場でトランザクション
コンテナキャッシュ
一回の実行単位でDIコンテナの起動は一回だけ

ブログが参考になります

サンプルコードがブログに載っています。

Exampleも参考になります

DBFlute Example では豪快に使っています。

UTFluteの環境構築

JUnit の jar は 3 でも 4 でも

UTFlute は、JUnit3 方式を採用しています。

ですが、利用する Junit のバージョンは 3 でも 4 でもどちらでも構いません。 (JUnit4 でも、JUnit3 の TestCase クラスが同梱されているので)

Maven の dependency 設定 (DIコンテナ利用なら)

Maven の pom.xml に、利用するDIコンテナに対応する UTFlute を指定します。

0.5.0
DBFluteランタイム 1.1.0 以降 ※こちらは Java8 対応です
0.4.5
DBFluteランタイム 1.0.5F 以降 ※万が一、ズレてても一部メソッドが利用できないだけ
0.4.4
DBFluteランタイム 1.0.5F より前

1.1.x対応のDependency

e.g. Seasarを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.dbflute.utflute</groupId>
      <artifactId>utflute-seasar</artifactId>
      <version>0.5.0-sp6</version>
      <scope>test</scope>
    </dependency>
e.g. Springを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.dbflute.utflute</groupId>
      <artifactId>utflute-spring</artifactId>
      <version>0.5.0-sp6</version>
      <scope>test</scope>
    </dependency>
e.g. Guiceを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.dbflute.utflute</groupId>
      <artifactId>utflute-guice</artifactId>
      <version>0.5.0-sp6</version>
      <scope>test</scope>
    </dependency>
e.g. LastaFluteを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.dbflute.utflute</groupId>
      <artifactId>utflute-lastaflute</artifactId>
      <version>0.5.0-sp6</version>
      <scope>test</scope>
    </dependency>

1.0.x対応のDependency

e.g. Seasarを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-seasar</artifactId>
      <version>0.4.8</version>
      <scope>test</scope>
    </dependency>
e.g. Springを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-spring</artifactId>
      <version>0.4.8</version>
      <scope>test</scope>
    </dependency>
e.g. Guiceを使っている場合の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-guice</artifactId>
      <version>0.4.8</version>
      <scope>test</scope>
    </dependency>

Maven の repository は、DBFlute Runtime と同じです。

web対応のDependency

さらに、HttpServlet の Mock を利用したい場合は、Spring と Guice に関しては "-web" を付けます。 (Seasarは、そもそも Servlet への依存を持っていて、"-web" なしでも Mock が利用できます)

e.g. Springと Web Mock の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-spring-web</artifactId>
      <version>0.4.8</version>
      <scope>test</scope>
    </dependency>
e.g. Guiceと Web Mock の UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-guice-web</artifactId>
      <version>0.4.8</version>
      <scope>test</scope>
    </dependency>

DIコンテナを使わず、UTFluteをPlainに使うのであれば、utflute-coreを指定します。

スーパークラスを継承 (DIコンテナ利用なら)

ContainerTestCase というクラスが用意されています。DIコンテナを利用するテストケースでは、このクラスを継承します。 こうすることで、テストケース起動時にDIコンテナが起動して、inject()が利用できるようになります。(後述のDI設定が必要です)

そのプロジェクト独自に、設定や挙動を変更するために、ContainerTestCaseを継承したプロジェクト独自のスーパークラスを用意することが推奨されます。 例えば、UnitContainerTestCase, Unit[プロジェクト名]ContainerTestCase というような名前が習慣です。

e.g. 独自のスーパークラスを作成、DI設定を変えたり @Java
public abstract class UnitContainerTestCase extends ContainerTestCase {

    @Override
    protected String prepareConfigFile() { // これは Seasar の場合
        return "test_app.dicon"; // テスト用のdiconを読み込むように変更
    }
}
e.g. ContainerTestCaseを継承してDIを利用できるように @Java
public class FooActionTest extends UnitContainerTestCase {

    public void test_index_basic() {
        // ## Arrange ##
        FooAction action = new FooAction();
        inject(action); // 起動したDIコンテナを利用してDIする

        // ## Act ##
        action.index();
        ...
    }
}

DIコンテナを利用しないテストケースでは、PlainTestCase というスーパークラスが用意されています。UTFluteの便利なメソッドが利用できるようになります。 (ContainerTestCaseも、これを継承しています)

e.g. 独自のスーパークラスを継承してテストケースを書く @Java
public class FooActionTest extends PlainTestCase {

    public void test_index_basic() {
        cannonball(...); // マルチスレッドのテストなど
    }
}

SeasarのDI設定

UTFluteは、DIコンテナを起動してテストケースを実行することをメインにしたツールですので、DIコンテナを起動する必要があります。

Seasarにおいては、デフォルトで app.dicon を読み込みます。

もし、テスト用の dicon を利用したい場合は、prepareConfigFile() メソッドをオーバーライドして、UTFluteが読み込むDIファイルを差し替えることができます。

e.g. 独自のスーパークラスでDI設定を変える (Seasar) @Java
public abstract class UnitContainerTestCase extends ContainerTestCase {

    @Override
    protected String prepareConfigFile() {
        return "test_app.dicon"; // テスト用のdiconを読み込むように変更
    }
}

UTFluteは、DIコンテナ起動時はデータベースとトランザクションを利用することが前提です。 読み込んだ dicon ファイルにて、javax.sql.DataSource と javax.transaction.TransactionManager がDIできる必要があります。 つまり、jdbc.diconが読み込まれていればOKです。

dbflute-seasar-example が参考になります。

DBFlute Example - DIコンテナ

SpringのDI設定

Springにおいては、デフォルトで beanRefContext.xml を読み込みます。

もし、テスト用の XML を利用したい場合は、prepareConfigFiles() メソッドをオーバーライドして、UTFluteが読み込むDIファイルを差し替えることができます。

e.g. 独自のスーパークラスでDI設定を変える (Spring) @Java
public abstract class UnitContainerTestCase extends ContainerTestCase {

    @Override
    protected String[] prepareConfigFiles() {
        return new String[] {"testBeans.xml"}; // テスト用のXMLを読み込むように変更
    }
}

UTFluteは、DIコンテナ起動時はデータベースとトランザクションを利用することが前提です。 読み込んだ XML にて、javax.sql.DataSource と (Springの) PlatformTransactionManager がDIできる必要があります。

dbflute-spring-example が参考になります。

DBFlute Example - DIコンテナ

GuiceのDI設定

Guiceにおいては、デフォルトでは何も読み込みません。

prepareModuleList() メソッドをオーバーライドして、UTFlute に Module をプッシュします。

e.g. 独自のスーパークラスでDI設定を指定する (Guice) @Java
public abstract class UnitContainerTestCase extends ContainerTestCase {

    @Override
    protected List<Module> prepareModuleList() {
        DataSource dataSource = createDataSource();
        List<Module> moduleList = new ArrayList<Module>();
        moduleList.add(new DBFluteModule(dataSource));
        moduleList.add(createTransactionModule(dataSource));
        return moduleList;
    }

    ...
}

UTFluteは、DIコンテナ起動時はデータベースとトランザクションを利用することが前提です。 読み込んだ Module にて、javax.sql.DataSource と TransactionManager がDIできる必要があります。

dbflute-guice-example が参考になります。

DBFlute Example - DIコンテナ

Plainに使うなら (DIコンテナ利用なし)

DIコンテナは使わないプロジェクトで、UTFluteを単なるテスト支援ツールとして利用するのであれば、utflute-coreを指定します。

e.g. plainな使い方をするときの UTFlute の dependency 設定 @pom.xml
    <dependency>
      <groupId>org.seasar.dbflute</groupId>
      <artifactId>utflute-core</artifactId>
      <version>0.4.8</version>
    </dependency>

そして、PlainTestCase を継承してテストケースを作成します。

DIコンテナやトランザクション処理に依存していない、markHere() や cannonball(), projectA(), policeStoryOf...() などの機能が利用できます。

e.g. PlainTestCaseを継承して、plainな機能を使う @Java
public class FooTest extends PlainTestCase {

    public void test_demo() { // メソッド名が test で始まること
        markHere("called");
        assertMarked("called");
        
        cannonball(...);
        policeStoryOf...(...);
        ...
    }
}

そもそも、DIコンテナを利用した ContainerTestCase などは、この PlainTestCase を継承しています。