S2JUnit4を導入してみた。
サクッとはいかなかったのでメモを残しておく。

前提

  • s2なプロジェクトがmavenプロジェクトとしてすでにある

導入方法

  1. test/resourcesにs2junit4.diconを追加
    S2Junit4のサイトのデフォルトのs2junit4.dicon そのままで。
    <?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"/>
      <component class="org.seasar.framework.unit.impl.DataAccessorImpl"/>
      <component class="org.seasar.framework.unit.impl.ConfigFileIncluderImpl">
        <initMethod name="addConfigFile">
          <arg>"javaee5.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>
      <component class="org.seasar.framework.unit.impl.ExpectedDataReaderImpl">
        <initMethod name="addExpectedDataXlsPath">
          <arg>context.testClassShortName + "_" + context.testMethodName + "_Expected" + ".xls"</arg>
        </initMethod>
      </component>
    </components>
    
  2. テストを動かしてみる。以下のエラーが発生
    org.seasar.framework.beans.IllegalPropertyRuntimeException: [ESSR0059]クラス(org.seasar.framework.jpa.impl.PersistenceUnitManagerImpl)のプロパティ(entityManagerProvider)の設定に失敗しました。理由はorg.seasar.framework.container.IllegalAutoBindingPropertyRuntimeException: [ESSR0080]クラス(org.seasar.framework.jpa.impl.EntityManagerProviderImpl)のプロパティ(dataSourceFactory)の自動設定に失敗しました
    at org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:297)
    at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindAuto(AbstractBindingTypeDef.java:164)
    at org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:45)
    :
    Caused by: org.seasar.framework.container.IllegalAutoBindingPropertyRuntimeException: [ESSR0080]クラス(org.seasar.framework.jpa.impl.EntityManagerProviderImpl)のプロパティ(dataSourceFactory)の自動設定に失敗しました
    at org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:46)
    at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:91)
    at org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:50)
    :
    
  3. dataSourceFactoryがないっぽいので、test/resourcesにjdbc.diconを追加してみる
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
      "http://www.seasar.org/dtd/components21.dtd">
    <components namespace="jdbc">
      <include path="env.dicon"/>
      <include path="jta.dicon"/>
      <component name="xaDataSource"
        class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
      <property name="driverClassName">
        "com.mysql.jdbc.Driver"
      </property>
      <property name="URL">xxxxxxxx</property>
      <property name="user">xxxxxxxx</property>
      <property name="password">xxxxxxxx</property>
    </component>
    <component name="connectionPool"
      class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
      <property name="timeout">600</property>
      <property name="maxPoolSize">100</property>
      <property name="allowLocalTx">true</property>
      <property name="validationQuery">"SELECT 1"</property>
      <destroyMethod name="close"/>
    </component>
    <component name="DataSource"
    class="org.seasar.extension.dbcp.impl.DataSourceImpl"
    />
    </components>
    

    →同じエラーが発生
    よくよく考えるとmain/resourceにあるjdbc.diconと同じものをtestにもってきても同じに決まってる。
  4. 悩んで調べる
    答えがここに!
    S2JDBC + S2JUnit4でハマる – idesaku blog
  5. test/resourcesのjdbc.diconに
    <include path="jdbc-extension.dicon"/>
    
    を追加する。
  6. テストを再実行
    通った!

テストクラスの書き方

  • テストクラスに@RunWithアノテーションをつける
    • 値はSeasar2.class
  • requestなどの暗黙オブジェクトはprivateフィールド書いておけばインジェクションされる
    • が、実体はMockHttpServletRequestなどのモックになっている
    • キャストすればいい
      @RunWith(Seasar2.class)
      public class XxxActionTest {
        private HttpServletRequest request;
        private HttpServletResponse response;
        @Test
        public void xxxxx() {
          MockHttpServletResponse mockResponse = (MockHttpServletResponse) response;
          :
      

指定したメソッドだけテスト実行できない

指定したメソッドだけ実行すると、以下のエラーが出た。

java.lang.NoSuchMethodError: org.junit.runner.manipulation.Filter.apply(Lorg/junit/runner/Runner;)V
at org.seasar.framework.unit.Seasar2.filter(Seasar2.java:183)
at org.junit.runner.manipulation.Filter.apply(Filter.java:79)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:34)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:32)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestMethodReference.<init>(JUnit4TestMethodReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:31)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

→junitを4.7から4.4に下げると解消した
参考 : Seasar2ではまったこと – nazonoDiary

よくよく 公式ページ を見ると、「JUnit4.4が必要です」とハッキリ書いてあった。

Seasarはプロダクトはすばらしいのに、ドキュメントがアレなのか、何するにしてもスッといかないのがもったいないなあ。

————————
以下に続きます。
S2JUnit4でSAStrutsのActionをテストする | roundropブログ implements Programmable