前の二つの記事でCDIとJPAをユニットテストで使う方法について書いてきたから詳細なプログラムの内容はそっちに任せるとして、
まとめたパッケージを簡単に使う方法をまとめると、pom.xmlをこんな感じに。
<repositories>
……
<repository>
<id>Empressia</id>
<url>http://www.empressia.jp/maven/</url>
</repository>
</repositories>
<dependencies>
……
<dependency>
<groupId>jp.empressia</groupId>
<artifactId>jp.empressia.test</artifactId>
<version>1.0.1-1</version>
<scope>test</scope>
</dependency>
</dependencies>
これでRunner指定すればCDIが使えるよ。さらにbeans.xmlをこんな感じに。
<beans>
<alternatives>
<stereotype>jp.empressia.test.UnitTest</stereotype>
</alternatives>
<intercepters>
<class>jp.empressia.test.TransactionInterceptor</class>
</intercepters>
</beans>
これでJPAとJTAが使える。一部だけど。
で、Maven使ってるときに気をつけないといけないことがあるんだよね。
beans.xmlにalternatives書くのは、main側じゃないとダメって言うか、main側のパスに入ってないとだめなのね。
でも、main側にテストの要素書いちゃだめなわけで……えーっと、
mainのclassesとtest-classesで別のbeans.xm管理になるって言う感じ?
実際にalternativeしたいのは、main側。設定書いておきたいのはtest側。
有効にするためには、test側にもbeans.xml必要。
うーん……ここ、ポイントだからしっかり整理〜。
- JavaEEの環境だと、beans.xml無くてもCDIは有効になる。
- JavaSEの環境だとbeans.xmlが必要。
- Mavenだとクラスファイルの格納場所が、classesとtest-classesに分かれてる。
- ユニットテストでalternativeの書いたbeans.xmlを置かないといけないのはclasses側(試して見た感じ)。
- ユニットテストでCDIを有効にするためにbeans.xml置くのはtest-classes側(中身は何でもよさそう)(試して見た感じ)。
- テスト固有のbeans.xmlの内容はmain側じゃなくてtest側に書いておきたい。
これを解決しようとすると、
testするときには、テスト側のbeans.xmlをmain側において実行して、
パッケージするときは、メイン側のbeans.xmlで上書きするって手順にしないとダメそう。
あと、persistence.xmlもmain側だけじゃなくてtest側にもおいちゃうと、ユニットテストの時に、EclipseLinkを使った時点で両方読まれちゃう。
test用にRESOURCE_LOCALで細かい接続設定書いたpersistence.xmlを置くだろうから、
ユニットテストの時はmainの方を消すのを忘れずに。packagingの時にこれも気をつけないとね。
具体的にはMavenのビルドをこんな感じに。
良い悪いいろんな意見はあるだろうけど、まぁ、手軽にやるなら良いかなって。
<build>
<plugins>
……
<!-- process-test-resources:beans.xmlをmainのclassesにコピーする。test側のbeans.xmlに書かれた内容をユニットテストの時に読み込まれるようにする。 -->
<plugin>
<groupId>com.github.goldin</groupId>
<artifactId>copy-maven-plugin</artifactId>
<version>0.2.5</version>
<executions>
<execution>
<id>copy test beans.xml to main for unit test.</id>
<phase>process-test-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<resources>
<resource>
<targetPath>${project.build.directory}/classes/META-INF</targetPath>
<file>src/test/resources/META-INF/beans.xml</file>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- process-test-resources:persistence.xmlをmainのclassesから削除する。mainのpersistence.xmlがユニットテストの時に読み込まれるのを防止する。 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
<executions>
<execution>
<id>remove persistence.xml from classes for avoiding duplicated persistence.xml at unit test.</id>
<phase>process-test-resources</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.directory}/classes/META-INF</directory>
<includes>
<include>persistence.xml</include>
</includes>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- テスト用にtargetが書き換えているから、src側からパッケージする。 -->
<webResources>
<resource>
<directory>src/main/resources/META-INF</directory>
<targetPath>WEB-INF/classes/META-INF</targetPath>
<includes>
<include>beans.xml</include>
<include>persistence.xml</include>
</includes>
</resource>
<resource>
<directory>target/classes/META-INF</directory>
<excludes>
<!-- beans.xmlはユニットテストの時にmain側にコピーしてるから取り込まないようにする。 -->
<exclude>beans.xml</exclude>
<!-- persistence.xmlはユニットテストの時に消えるはずだけどincludeと形をあわせておく。 -->
<exclude>persistence.xml</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
ここまでで、@Injectが使いたい放題でJPAのPersistenceUnit1個に対応して、Transactionalにも簡単にだけど対応した状態になっているはず!(゜▽、゜
気に入らなければCDIの力で差し替えも簡単だから、是非、お試しあれ?(゜▽、゜