|
|
WebOTX Manual V11.2 (第2版) 目次を表示 |
Arquillianは、Jakarta EEアプリケーションのテスト・フレームワークです。
本章ではArquillian を利用して、Jakarta EEアプリケーションのテストを行う手順に関する
説明を行います。
アプリケーションは、mavenでビルドする前提であり、maven 3.0以上が必要です。
WebOTX Arquillian では、Managed モードと Remote モードをサポートしています。
WebOTX Arquillian と同一マシン上の WebOTX Application Server を利用する場合は Managed モード、リモートマシン上で動作するWebOTX Application Server を利用する場合は Remoteモードを使用します。
ServletからEJBを利用するアプリケーションを例に、テストの進め方について説明します。
以下の構成のアプリケーション(Servlet と EJB を含む)をテスト対象とします。
+---pom.xml
+---src
+---main
| +---java
| | \---sample
| | Greeter.java
| | GreeterServlet.java
| |
| +---resources
| \---webapp
|
\---test
+---java
| \---sample
| GreeterServletTest.java
| GreeterTest.java
|
\---resources
arquillian.xml
EJB(Greeter.java)の実装例を以下に記載します。
package sample;
import javax.ejb.Stateless;
import java.io.Serializable;
@Stateless
public class Greeter implements Serializable {
private static final long serialVersionUID = 1L;
public String greet() {
return "Hello arquillian sample.";
}
}
Webアプリケーション(GreeterServlet)の実装例を以下に記載します。
package sample;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/greeter")
public class GreeterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
private Greeter greeter;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append(this.greeter.greet());
}
}
pom.xml の定義例を以下に記載します。
<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>sample</groupId>
<artifactId>hello-arquillian-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakarta.jakartaee-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Arquillian でテストするために pom.xml に追加が必要な dependency の定義について、以下に記載します。
Arquillian-JUnitインテグレーションを加えるために、以下の dependency の追加が必要です。
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<version>1.6.0.Final</version>
<scope>test</scope>
</dependency>
JUnit のテストコードを記述するために、以下の dependency の追加が必要です。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
Remoteモードの場合は、以下の定義が必要です。
<dependency>
<groupId>com.nec.webotx.arquillian.container</groupId>
<artifactId>arquillian-webotx-remote</artifactId>
<version>11.2.0</version>
<scope>test</scope>
</dependency>
Managed モードの場合は、以下の定義が必要です。
<dependency>
<groupId>com.nec.webotx.arquillian.container</groupId>
<artifactId>arquillian-webotx-managed</artifactId>
<version>11.2.0</version>
<scope>test</scope>
</dependency>
ここまでに説明した dependency を追加すると、Remoteモードの場合の pom.xml は以下のようになります。
<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>sample</groupId>
<artifactId>hello-arquillian-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
<junit.version>4.13.2</junit.version>
<arquillian.version>1.6.0.Final</arquillian.version>
<webotx-arquillian.version>11.2.0</webotx-arquillian.version>
<hamcrest.version>1.3</hamcrest.version>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakarta.jakartaee-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.nec.webotx.arquillian.container</groupId>
<artifactId>arquillian-webotx-remote</artifactId>
<version>${webotx-arquillian.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/test/java 配下に GreeterServletTest を作成します。
パッケージ名は sample とします。
package sample;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.servlet.annotation.WebServlet;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
@RunWith(Arquillian.class)
public class GreeterServletTest {
@Deployment
public static WebArchive getTestArchive() {
final WebArchive war = ShrinkWrap.create(WebArchive.class, "hello-arquillian-sample.war")
.addClasses(GreeterServlet.class, Greeter.class);
return war;
}
@Test
public void assertWarDeployed() throws Exception {
final String servletPath = GreeterServlet.class.getAnnotation(WebServlet.class).urlPatterns()[0];
final URLConnection response
= new URL("http://localhost:8080/hello-arquillian-sample" + servletPath).openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(response.getInputStream()));
final String result = in.readLine();
assertEquals("Hello arquillian sample.", result);
}
}
太字部分は、Arquillian を利用するテストアプリケーションにおいて必須です。
@Deployment アノテーションを付加したpublic static メソッドでは、ShrinkWrapアーカイブを返す処理を行います。
addClasses メソッドでは、warファイルに含めるクラスを指定します。
URLのポート番号はテスト対象のアプリケーションが配備されているドメインの HTTP ポート番号を指定します。
Memo
テスト対象のwarやjarに含めているファイルはすべてArchiveを作成時に含める必要があります。
例えば、jspを含むWebアプリケーションなら、warファイルのArchiveにjspも含める必要があります。
src/test/resources/arquillian.xml を作成し Arquillian の設定を行います。以下の定義例では、adminUser と adminPassword に環境変数の値を設定しています。
arquillian.xmlの定義例
<arquillian
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="webotx-arquillian-remote"
default="true">
<configuration>
<property name="adminHost">localhost</property>
<property name="adminPort">6212</property>
<property name="adminUser">${env.OTX_ADMIN_USER}</property>
<property name="adminPassword">${env.OTX_ADMIN_PASSWORD}</property>
<property name="encryptAdminPassword">true</property>
</configuration>
</container>
</arquillian>
arquillian.xmlの項目説明
arquillian.xml で設定可能な項目について、以下に記載します。
| 項目 | 設定値 | 既定値 | Remote | Managed | 備考 |
|---|---|---|---|---|---|
| adminHost | 文字列 | localhost | 〇 | 〇 | WebOTXが動作しているホスト名/IPアドレス。 |
| adminPort | 1〜65535 | 6212 | 〇 | 〇 | 運用管理ポート。 |
| protocol | rmi/jmxmp | rmi | 〇 | 〇 | プロトコル(RMI/JRMPまたはJMXMP)。 |
| secure | true/false | false | 〇 | 〇 | SSLの設定。JMXMPの場合に適用。RMI/JRMPの場合、 false 固定。 |
| tlsVersion | 文字列 | TLSv1.2 | 〇 | 〇 | TLSバージョン。secure が trueの場合に使用する。 |
| cipherSuites | 文字列 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA | 〇 | 〇 | 暗号化スイート。secure が trueの場合に使用する。 |
| adminUser | 文字列 | - | 〇 | 〇 | 運用管理ユーザ名。 |
| adminPassword | 文字列 | - | 〇 | 〇 | 運用管理ユーザのパスワード。 |
| encryptAdminPassword | true/false | false | 〇 | 〇 | adminPasswordが暗号化されているかを指定する。※adminPasswordには、開発者がencryptコマンドを使用し、暗号化したパスワードを生成し設定する。 |
| useHttps | true/false | false | 〇 | 〇 | テスト時に実行するリクエストにHTTPSを使用するかどうか。 |
| webotxHome | 文字列 | - | - | 〇 | WebOTXインストールディレクトリ。 |
| domain | 文字列 | - | - | 〇 | ドメイン名。${webotxHome}/domains/配下に存在すること。 |
| debug | true/false | false | - | 〇 | WebOTXをデバッグ・モードで起動するためのフラグ。 |
| allowConnectingToRunningServer | true/false | false | - | 〇 | Arquillianが既に実行中のWebOTXインスタンスに接続することを許可するフラグ。 |
| deleteDeployFile | true/false | true | 〇 | 〇 | 配備時に使用するアーカイブファイルを削除するかどうか。(問題発生時の調査ために配備したファイルを確認する等で使用することを想定。) |
| waitDynamicReflection | 0〜 | 0 | 〇 | 〇 | 動的反映待ち合わせ時間。ミリ秒で指定。 |
ここまで作業した結果、パッケージエクスプローラに表示される構成は以下のようになります。
Remote モードの場合は、テスト実行前にテスト対象のアプリケーションを配備しているドメインを起動しておく必要があります。
まずは実行構成を設定します。
新規作成します。
プロジェクト、テストクラスを確認します。
「環境」タブを選択し、環境変数の設定を行います。
「実行」ボタンをクリックするとテストが実施されます。
続いて、EJB(Greeter.java) のテストコードを作成します。
src/test/java 配下に GreeterTest を作成します。
パッケージ名は sample とします。
package sample;
import static org.junit.Assert.*;
import javax.ejb.EJB;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(Arquillian.class)
public class GreeterTest {
@EJB
Greeter greeter;
@Deployment
public static JavaArchive getTestArchive() {
final JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "greeter-ejb.jar")
.addClasses(Greeter.class);
return jar;
}
@Test
public void test() {
assertNotNull(greeter);
assertEquals("Hello arquillian sample.", greeter.greet());
}
}
太字部分は、Arquillian を利用するテストアプリケーションにおいて必須です。
@Deployment アノテーションを付加したpublic static メソッドでは、ShrinkWrapアーカイブを返す処理を行います。
ShrinkWrap.create メソッドで、jarファイルを作成します。
addClasses メソッドでは、jarファイルに含めるクラスを指定します。
Memo
使用するプロトコル(http/https)の制御は useHttps で指定します。
既定では useHttps は false で http ポートを使用します。
https を使用する場合は、useHttps に true を指定します。
更に、defaultProtocol の設定で scheme に https を指定します。
パスワードを暗号化する場合は、encryptコマンドで暗号化したパスワードを生成します。以下に実行例を記載します。
otxadmin> encrypt
CLI261 暗号化する文字を入力してください:
CLI262 もう一度入力してください:
<暗号化されたパスワード>
コマンド encrypt は正常に実行されました。
arquillian.xml の adminPassword に暗号化されたパスワードを設定します。
Arquillianではドメインから情報を取得したり、配備・配備解除を行うために JMX 通信を使用します。
JMX通信で使用するプロトコルをRMI/JRMPまたはJMXMPを protocol で指定します。
RMI/JRMP を使用する場合は、rmi(既定値) を、JMXMP を使用する場合は jmxmp を指定します。
JMXMP を使用する場合は、マニュアルの以下の箇所を参照しJMXMPを有効にしてください。
Application Server > 構築・運用 > ドメインの構築 1.12.1. JMXMPを利用する手順
JMX通信で SSL を使用する場合も JMXMP を使用してください。
次に JMXMP で SSL を使用する場合の arquillian.xml の設定を記載します。
<pre class="source">
:
<container qualifier="webotx-arquillian-remote"
default="true">
<configuration>
:
<property name="protocol">jmxmp</property>
<property name="secure">true</property>
</configuration>
</container>
</pre>
:
また、TLSバージョンや、暗号化スイートを既定から変更したい場合は、tlsVersion、cipherSuites で指定してください。
ネットワークの接続設定がNAT接続の場合、ドメインの接続プロトコルとして、RMI/JRMP は利用できないため、JMXMP を使用します。
次の図の構成例の場合の対処方法を説明します
テスト対象のアプリケーションを配備しているドメインの設定にて、JMXMPプロトコルを有効にします。 マニュアルの以下の箇所を参照し、設定を行ってください。
Application Server > 構築・運用 > ドメインの構築 1.12.1. JMXMPを利用する手順arquillian.xml の設定では、protocol にjmxmp を設定します。
WebOTX では JMXMP は既定で SSL を使用するようになっているため、WebOTX側の設定を変更していない場合は secure を true に設定します。
defaultProtocol の設定も必要であり、defaultProtocol の設定を行わない場合は以下のようなエラーが発生します。
java.lang.IllegalStateException: Error launching test sample.GreeterServletTest public void sample.GreeterServletTest.assertWarDeployed() throws java.lang.Exception
:
Caused by: java.lang.IllegalStateException: Error launching request at http://localhost:8080/hello-arquillian-sample/ArquillianServletRunner?outputMode=serializedObject&className=sample.GreeterServletTest&methodName=assertWarDeployed. No result returned
at org.jboss.arquillian.protocol.servlet.ServletMethodExecutor.executeWithRetry(ServletMethodExecutor.java:130)
at org.jboss.arquillian.protocol.servlet.ServletMethodExecutor.invoke(ServletMethodExecutor.java:102)
... 79 more
arquillian.xml の設定例を以下に記載します。
:
<defaultProtocol type="Servlet 3.0">
<property name="host">192.168.100.100</property>
<property name="port">28080</property>
</defaultProtocol>
<container qualifier="webotx-arquillian-remote" default="true">
<configuration>
:
<property name="adminHost">192.168.100.100</property>
<property name="adminPort">26712</property>
<property name="protocol">jmxmp</property>
<property name="secure">true</property>
</configuration>
</container>
:
ビルドで生成した EAR ファイルを取得し、テストクラスを追加する例を以下に示します。
+---pom.xml
+---auto-test
| | pom.xml
| |
| +---src
| | \---test
| | +---java
| | | \---sample
| | | AutoTest.java
| | |
| | \---resources
| | arquillian.xml
| |
| \---target
| auto-test-1.0.jar
|
+---ear-module
| | pom.xml
| |
| \---target
| ear-module-1.0.ear
|
+---ejb-module
| | pom.xml
| |
| +---src
| | +---main
| | | +---java
| | | | \---sample
| | | | Greeter.java
| | | |
| | | \---resources
| | \---test
| | +---java
| | \---resources
| \---target
| ejb-module-1.0.jar
|
\---war-module
| pom.xml
+---src
| +---main
| | +---java
| | | \---sample
| | | GreeterServlet.java
| | |
| | +---resources
| | \---webapp
| \---test
| +---java
| \---resources
\---target
war-module-1.0.war
テストコードのサンプルソース(AutoTest.java)を以下に記載します。
package sample;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.importer.ZipImporter;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.api.Archive;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(Arquillian.class)
public class AutoTest {
@ArquillianResource
private URL deploymentUrl;
@Deployment
public static Archive<?> createDeployment() {
EnterpriseArchive ear = ShrinkWrap.create(ZipImporter.class, "ear-module-1.0.ear")
.importFrom(new File("../ear-module/target/ear-module-1.0.ear")).as(EnterpriseArchive.class);
WebArchive web = ear.getAsType(WebArchive.class, "war-module-1.0.war");
web.addClasses(AutoTest.class);
return ear;
}
@Test
public void assertRequest() throws Exception {
final URLConnection response
= new URL(deploymentUrl.toString() + "/greeter").openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(response.getInputStream()));
final String result = in.readLine();
assertEquals("Hello arquillian sample.", result);
}
}
ShrinkWrap.create でテスト対象のearファイルを指定します。
ear.getAsType でwarファイルを取得します。
addClasses でテストクラスをwarファイルに追加します。
rar ファイルを含むアプリケーションをテストするには、earファイルにrarを含める必要があります。
なし