SAStrutsを勉強してみる (4) - S2JUnit4でテスト -

2012-10-05T00:00:00+00:00 Java SAStruts

タイトル通り。まだ(調査が)微妙なんですが、S2Unit4を使ってテストをしてみる

s2junit4.dicon

が必要な模様なのですが、 http://s2container.seasar.org/2.4/ja/S2JUnit4.html に普通に書いてあるのでそのまま抜粋する。ちょっと削ってる

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
  "http://www.seasar.org/dtd/components24.dtd">
<components namespace="s2junit4">
  <component name="context" class="org.seasar.framework.unit.impl.InternalTestContextImpl">
    <!-- これをやるとテストデータがそっくりそのまま入れ替わる -->
    <!-- 詳しくはhttp://s2container.seasar.org/2.4/ja/S2JUnit4.html#tipsAllReplace -->
    <property name="preparationType">@org.seasar.framework.unit.PreparationType@ALL_REPLACE</property>
  </component>
  <component class="org.seasar.framework.unit.impl.DataAccessorImpl"/>
  <component class="org.seasar.framework.unit.impl.ConfigFileIncluderImpl">
    <initMethod name="addConfigFile">
      <arg>"app.dicon"</arg>
    </initMethod>
    <initMethod name="addConfigFile">
      <arg>context.testClassShortName + ".dicon"</arg>
    </initMethod>
  </component>
  <component class="org.seasar.framework.unit.impl.TestDataPreparerImpl">
    <initMethod name="addTestDataXlsPath">
      <arg>context.testClassShortName + "_" + context.testMethodName + ".xls"</arg>
    </initMethod>
    <initMethod name="addTestDataXlsPath">
      <arg>context.testClassShortName + ".xls"</arg>
    </initMethod>
  </component>
</components>

ってな感じで、テストクラス名.xlsもしくはテストクラス名_テストメソッド名.xlsを使えばテストデータをぶち込める模様

SampleTestCase.xls

上で書いたようにテストデータをぶち込めるExcelファイルを作成する

っていう感じで1行目にテーブルのカラム名、それ以降にそれに対応するデータをぶち込む(Date系の場合、列書式を日付にすれば挿入できるらしいですけど未だ成功せず)

また、シート名はテーブル名にしておく(初期時の要らないシートは消しておく)

SampleService.java

package sample.service;

import java.util.List;
import javax.annotation.Resource;

import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.OrderByItem;
import org.seasar.extension.jdbc.exception.SEntityExistsException;
import org.seasar.framework.exception.SQLRuntimeException;

import sample.entity.Sample;

public class SampleService {

    @Resource
    private JdbcManager jdbcManager;

    public List<Sample> getSamples() {
        OrderByItem order = new OrderByItem("id", OrderByItem.OrderingSpec.DESC);

        return jdbcManager.from(Sample.class).orderBy(order).getResultList();
    }

    public Sample createSample(Sample sample) {
        Sample createdSample = null;

        try {
            int rowUpdate = jdbcManager.insert(sample).execute();

            if (rowUpdate > 0) {
                createdSample = sample;
            }
        } catch (SEntityExistsException e) {
            e.printStackTrace();
        } catch (SQLRuntimeException e) {
            e.printStackTrace();
        }

        return createdSample;
    }
}

この2つのメソッドをテストで使うので定義しておく。あくまで例で、前回のS2JDBCな記事がベース(但し、Date系のカラムは修正)

Sample2Action.java

package sample.action;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.seasar.struts.annotation.Execute;

import sample.entity.Sample;
import sample.service.SampleService;

public class Sample2Action {

    @Resource
    private HttpServletRequest request;

    @Resource
    private HttpSession session;

    @Resource
    private SampleService sampleService;

    public List<Sample> samples;

    @Execute(validator = false, removeActionForm = true)
    public String index() {
        System.out.println(
            String.format("X-Framework = %s", request.getHeader("X-Framework"))
        );

        samples = sampleService.getSamples();

        session.setAttribute("test", "hoge fuga foobar");

        return "index.jsp";
    }
}

SampleTestCase.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.seasar.framework.mock.servlet.MockHttpServletRequest;
import org.seasar.framework.mock.servlet.MockHttpSession;
import org.seasar.framework.unit.Seasar2;
import org.seasar.framework.unit.annotation.TxBehavior;
import org.seasar.framework.unit.annotation.TxBehaviorType;

import sample.action.Sample2Action;
import sample.entity.Sample;
import sample.service.SampleService;

import static org.junit.Assert.*;

@RunWith(Seasar2.class)
public class SampleTestCase {

    private MockHttpServletRequest request;
    private MockHttpSession session;

    private SampleService service;

    private Sample2Action action;

    @Test
    //@TxBehavior(TxBehaviorType.NONE)
    public void testAdd() {
        Sample sample = new Sample();
        sample.data = "test";

        // SampleService.createSampleでテーブルにデータを突っ込む
        assertNotNull(service.createSample(sample));

        // 突っ込んだあとのテーブルのサイズが4であるかチェック
        assertSame(service.getSamples().size(), 4);
    }

    @Test
    public void testActionIndex() {
        // リクエストヘッダーに値を突っ込む
        request.addHeader("X-Framework", "SAStruts (S2JUnit4)");

        // アクションメソッドを実行した結果をテスト
        assertSame(action.index(), "index.jsp");

        // アクションメソッドからぶち込まれたセッションデータをテスト
        assertSame(session.getAttribute("test"), "hoge fuga foobar");
    }
}

とりあえずフィールドに定義しとけば、S2Containerで注入される模様。んでテスト側でMockHttpServletRequest等を介する事でアクションメソッド実行のリクエストヘッダーなども注入されるっていう感じなのかも

んで、実行すると上で書いたテストデータがテスト前にぶち込まれる事を確認する。

備考1

ドキュメントではs2junit4.diconでjavaee.diconをインクルードしているけど、これだと何やら依存関係の注入でコケる。 http://blog.roundrop.jp/show/21 を参考にjavaee5.diconではなく、app.diconをインクルードする事で解決出来る模様

未解決要件1 (Txなメソッドがついてるとコミットされずにロールバックされる件)

何やらテストメソッドの接尾辞にTxがついてるとコミットされずにロールバックされるらしいが、つけようがつけまいがロールバックされてる模様げ

な感じでちょっとまだ微妙な所が多いので、分かり次第レポートする予定

SAStrutsを勉強してみる (5) - @Mockを使う - SAStrutsを勉強してみる (3) - S2JDBCを使う -