JPAを使うテストとクラスパスについて

上記のパーシステンス周りの実装をEclipse上でテストしようとすると、ちょっとコツがいりました。
もともと、テストとかも「activator ui」によるブラウザ上の開発環境で実行する前提で調整されているので
Eclipse環境はあまり優遇されていないようです。

そもそものPlayでのお作法も含めて、ざっくり言うと以下4点の対応が必要。

FakeApplicationを用意してあげる

Play上で動くコードはPlayが色々とお膳立てをしてくれているわけで、テストでも同じようにお膳立てをしてあげる必要があります。
これについてはネット上に色々情報がありますが、僕は以下のようなクラスを継承してテストを書きました。

public abstract class FakeApplicationTest {
    protected EntityManager em;
    FakeApplication app;

    @Before
    public void setUpTest() {
        this.app = fakeApplication();
        Helpers.start(this.app);
    }

    @After
    public void tearDownTest() {
        Helpers.stop(this.app);
    }
}

Transactionを用意してあげる

まあこれもおまじないみたいなもんです。
テストを書く際に、以下のように記述をしてあげます。

public class HogeTest extends FakeApplicationTest {

    @Test
    public void testHero() {
        JPA.withTransaction(new play.libs.F.Callback0() {
            public void invoke() {
              // テスト内容
            }
        });
    }

}

scala-libraryにクラスパスを通す

これは多分、Play-Javaの実装上のちょっとした手落ちなんじゃないかと思うんですけどね。
上記の記述でactivator ui 上では問題なく動くのですが、eclipse上からFakeApplicationを動かそうとすると怒られます。

java.lang.NoClassDefFoundError: scala/collection/Map
at testutil.FakeApplicationTest.setUpTest(FakeApplicationTest.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
・・・・・

つまり、FakeApplicationを動かすにはScalaのMap実装が必要なんですね。

仕方ないので、eclipse上で「scala-library-2.11.x.jar」とかを Build Path に含めてあげます。
(まあ、activator eclipseやると元に戻ってしまうのでカッコ悪いですが。。)

ちなみに、scala-libraryは.ivy/cache/org.scala-lang/scala-library/jars とかにいます。

「activator test」を実行する。

普通、eclipseで開発するときはコードを保存したらその瞬間コンパイルされて使えるようになりますが、
このPlayの環境ではどうやらそうではないようです。
「activator test」を実行することで、コンパイル内容がクラスパスに載ってくる感じの様です。
ちょっと面倒くさいですけどね。


とりあえず今回は以上。