JavaEEでもTDD - JPA編 - 1

JavaEEでUnitTest書く方法はモックを使うとかglassfish-embedded使うとか色々合ったわけですが、先日コンテナ非依存のテストツールであるArquillianがJBossより正式リリースしたので、試して見ることにしました。まずは、こないだ痛い目を見たのでJPA周りをTDDしてみます。開発環境はNetBeans 7.1.2, GlassFish 3.1.2ですが、Mavenベースにしてあるので、Eclipseでも問題なくそのまま動きました。

1. プロジェクトの作成

まずはプロジェクトの作成をします。「新規作成」 -> 「Maven」 -> 「Webアプリケーション」で作成します。

サーバはGlassFish 3.1.2を選択します。JBossとか別なのを使う場合は、後述のpom.xmlの設定を適当に変更してください。

プロジェクトの作成が終わったら、pom.xmlにArquillianはじめ必要なライブラリの設定等を追加していきます。長いのでブログには載せませんので、こちらを参照にしてください。

2. テスト対象の作成

次に、記事を表すEntityのArticleを作成します。普通にフルスクラッチしても良いのですが、面倒なのでNetBeansの「新規Entityの作成」である程度のひな形を作ります。これでArticleのひな形とpersistance.xmlが作成されたのが確認できると思います。

つづいて、Entityを操作するDAOクラスを作ります。「EntityクラスからセッションBean」を作成を選択して、利用Entityに先ほど作ったArticleを追加して完了します。DAOのArticleFacadeと抽象クラスのAbstractFacadeが作成されたのが確認できると思います。この辺が結構自動生成されるのがNetBeansの良い所です。

3. はじめてのテスト

では、早速、最初のテストを書いていきましょう。「新規JUnitテスト」でtest側の同一パッケージにArticleFacadeTestを作成します。

作成したテストクラスに下記の用にArquillian用の記述を追加します。

@RunWith(Arquillian.class)
public class ArticleFacadeTest {

    @PersistenceContext
    EntityManager em;
    @Inject
    UserTransaction utx;

    public ArticleFacadeTest() {
    }

    @Deployment
    public static Archive createDeployment() {
        return ShrinkWrap.create(WebArchive.class, "test.war").
                addPackage(Article.class.getPackage()).
                addPackage(ArticleFacade.class.getPackage()).
                addAsResource("META-INF/persistence.xml").
                addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    @EJB
    ArticleFacade articleFacade;
    
}

@Deploymentの 部分でテスト用のコンテナが立ち上がります。addPackageでは追加したいクラスのパッケージを登録します。addAsResourceで指定しているpersistance.xmlは今回は先程生成されたものが参照しています。beans.xmlはまだ作成していないので、

src/main/resources/META-INF/beans.xml

に空ファイルを作成します。

次は、persistance.xmlがテストで参照するデータソースを指定するためにsrc/test/resources/arquillian.xmlを下記のように作成ます。

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd">
    <engine>
        <property name="deploymentExportPath">target/arquillian</property>
    </engine>

    <container default="true" qualifier="glassfish">
        <configuration>
            <property name="sunResourcesXml">src/main/setup/glassfish-resources.xml</property>
        </configuration>
    </container>
</arquillian>

続いて、sunResourcesXmlで指定されているglassfish-resources.xmlを下記の通り作ります。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
    <jdbc-connection-pool name="arquillianPool" res-type="javax.sql.DataSource"
                      datasource-classname="org.apache.derby.jdbc.ClientDataSource"
                      pool-resize-quantity="1" max-pool-size="5" steady-pool-size="0"
                      statement-timeout-in-seconds="60" >
        <property name="serverName" value="localhost" />
        <property name="portNumber" value="1527" />
        <property name="dataBaseName" value="sun-appserv-samples" />
        <property name="User" value="APP" />
        <property name="Password" value="APP" />
        <property name="connectionAttributes" value=";create=true" />
        <property name="driverType" value="4" />
    </jdbc-connection-pool>
    <jdbc-resource jndi-name="jdbc/arquillian" pool-name="arquillianPool" /<
</resources>

これでテストの起動時に適切なDataSourceが作成されます。本番だとMySQLOracleになると思いますが、TDDの最中は手軽なDerbyを指定して見ました。ここを変更すればMySQL等でも使えるので、結合テストや負荷テストで変えて確認するがの良いかと思います。この辺のDBを切り替えやすいのはJPAの恩恵ですね。

では、ようやく本命のテストコードです。まずは、データを何も登録してないので、レコードが空であることを確認するテストを書きます。

    @Test
    public void count0_Test() throws Exception {
        assertThat(articleFacade.count(), is(0));
    }

gist:2893195(全文)

微妙にTDDの原則に反してますが、いきなりGreenになれば成功です。まあ、確認対象は自動生成コードなので、問題無いです。これが動けば、ひと通りの環境設定に誤りがないという事なので、あとはTDDを回していくだけです><

4. AbstractJPATestの作成

このまま進めても問題は無いのですが、後々の便利なので、ユーティリティメソッドとか共通フィールドを持った親クラスを作ります。内容はこんな感じ. 以降はこのコードを継承した前提で進めます。

 

思ったより長くなったので続きは次の記事で。なお、現在作成しているとこまではgithubのこちらのタグからcheckoutできます。

 

参考:

Arquillian Guide - Getting Started(日本語)

Arquillian Guide - Testing Java Persistance