Rhythm & Biology

Engineering, Science, et al.

WildFly: Arquillianを利用したテスト

WildFly+Arquillianでテストを実行してみたログ

環境

プロジェクト新規作成

  1. 新規プロジェクト → Maven → Webアプリケーション
  2. プロジェクト名: arq-base
  3. パッケージ: com.mythosil.arqbase
  4. サーバ: WildFly
  5. Java EE バージョン: Java EE 7 Web

テスト対象クラスの用意

まずはシンプルなセッションBeanをテスト対象クラスとして用意します

  • 新規 → セッションBean
    • EJB名: SimpleBean
    • 場所: ソース・パッケージ
    • パッケージ: com.mythosil.arqbase
    • セッションのタイプ: ステートレス
package com.mythosil.arqbase;

import javax.ejb.Stateless;

@Stateless
public class SimpleBean {
    public String hello(String name) {
        return String.format("Hello, %s", name);
    }
}

pom.xmlの用意

  • repositories
  • dependencyManagement
    • WildFlyとArquillianのBOMを追加
  • dependencies
    • EJBJUnit、Arquillianを依存に追加
  • profile
    • managed版とremote版をそれぞれ用意
    • arquillianの依存もそれぞれに合わせた物を依存に追加
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mythosil</groupId>
    <artifactId>arq-base</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>arq-base</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.protocol</groupId>
            <artifactId>arquillian-protocol-servlet</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.wildfly.bom</groupId>
                <artifactId>jboss-javaee-7.0-with-all</artifactId>
                <version>8.1.0.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>1.1.5.Final</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
    <profiles>
        <profile>
            <id>arq-wildfly-managed</id>
            <dependencies>
                <dependency>
                    <groupId>org.wildfly</groupId>
                    <artifactId>wildfly-arquillian-container-managed</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>arq-wildfly-remote</id>
            <dependencies>
                <dependency>
                    <groupId>org.wildfly</groupId>
                    <artifactId>wildfly-arquillian-container-remote</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
    
    <repositories>
        <repository>
            <id>JBoss Repository</id>
            <url>https://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
    </repositories>

</project>

テストの用意

  • 新規 → JUnitテスト
    • クラス名: SimpleBeanTest
    • 場所: テスト・パッケージ
    • パッケージ: com.mythosil.arqbase
  • RunWith
    • Arquillian.classを指定
  • テスト対象クラス
  • アーカイブ作成
    • Deploymentアノテーションを利用
    • ShrinkWrapクラスを利用し、テスト時にWildFlyにデプロイするアーカイブを生成
package com.mythosil.arqbase;

import javax.ejb.EJB;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class SimpleBeanTest {
    @EJB
    SimpleBean target;
    
    @Test
    public void testHello() {
        String actual = target.hello("myname");
        assertEquals("Hello, myname", actual);
    }
    
    @Deployment
    public static Archive<?> createTestArchive() {
        return ShrinkWrap.create(WebArchive.class)
                .addClass(SimpleBean.class);
    }
}

arquillian.xmlの用意

  • 新規 → XMLドキュメント
    • ファイル名: arquillian
    • フォルダ: src/test/resources/META-INF
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/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">
    
    <container qualifier="wildfly-managed" default="true">
        <configuration>
            <property name="jbossHome">WildFlyのインストール先</property>
        </configuration>
    </container>
    
    <container qualifier="wildfly-remote" default="false">
        <configuration>
            <property name="managementPort">9990</property>
            <property name="managementAddress">WildFlyサーバのアドレス</property>
            <property name="username">ユーザ名</property>
            <property name="password">パスワード</property>
        </configuration>
    </container>
    
</arquillian>

テスト実行

# managed版の実行
$ mvn clean test -Parq-wildfly-managed
...(中略)...
Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.780 s
[INFO] Finished at: 2014-09-04T01:04:17+09:00
[INFO] Final Memory: 29M/221M
[INFO] ------------------------------------------------------------------------

# remote版の実行
$ mvn clean test -Parq-wildfly-remote

テスト対象エンティティクラスの用意

エンティティクラスもテストしてみます
DBにはH2(インメモリ)を利用します

  • 新規 → エンティティクラス
    • クラス名: Person
    • 場所: ソース・パッケージ
    • パッケージ: com.mythosil.arqbase
    • 主キー型: Long
    • 持続性ユニット名: arqbasePU
    • 永続性プロバイダ: Hibernate (JPA2.1)
    • データ・ソース: java:jboss/datasources/test
package com.mythosil.arqbase;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    /* Setter, Getter */
}

pom.xml修正

<dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.1-api</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.jboss.spec.javax.transaction</groupId>
    <artifactId>jboss-transaction-api_1.2_spec</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <scope>provided</scope>
</dependency>

テスト用datasource作成

  • テスト用DBとしてH2(インメモリ)を利用
  • 新規 → XMLドキュメント
    • ファイル名: test-ds
    • フォルダ: src/test/resources/WEB-INF
<?xml version="1.0" encoding="UTF-8"?>
<datasources  xmlns="http://www.jboss.org/ironjacamar/schema">
    <datasource jndi-name="java:jboss/datasources/test" pool-name="TestDS" enabled="true" use-java-context="true">
        <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
        <driver>h2</driver>
        <security>
            <user-name>sa</user-name>
            <password>sa</password>
        </security>
    </datasource>
</datasources>

テストの用意

  • 新規 → JUnitテスト
    • クラス名: PersonTest
    • 場所: テスト・パッケージ
    • パッケージ: com.mythosil.arqbase
package com.mythosil.arqbase;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class PersonTest {
    @PersistenceContext
    EntityManager em;
    @Inject
    UserTransaction tx;
    
    @Test
    public void testPersist() throws Exception {
        Person target = new Person();
        target.setName("myname");
        
        tx.begin();
        em.joinTransaction();
        em.persist(target);
        tx.commit();
        em.clear();
        
        Person p = em.find(Person.class, 1L);
        assertEquals("myname", p.getName());
    }
    
    @Deployment
    public static Archive<?> createTestArchive() {
        return ShrinkWrap.create(WebArchive.class)
                .addClass(Person.class)
                .addAsResource("META-INF/persistence.xml")
                .addAsWebInfResource("WEB-INF/test-ds.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }
}

テスト実行

$ mvn clean test -Parq-wildfly-managed