以下の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/07/06/211629より取得しました。


Apache Tomcat 10.1 × Arquillian × JUnit 5でインテグレーションテスト(Managed/Remote)

これは、なにをしたくて書いたもの?

Apache TomcatでArquillianを使う時には、Tomcat向けのものを使います。

GitHub - arquillian/arquillian-container-tomcat: Arquillian Containers for Tomcat

前にEmbeddedでやろうとしてうまくいっていなかったのですが、ManagedとRemoteなら動かせたのでメモしておくことに
しました。

Arquillian Tomcat Containers

Apache TomcatでArquillianを使う時には、こちらのTomcat Containersを使います。

GitHub - arquillian/arquillian-container-tomcat: Arquillian Containers for Tomcat

サポートしている実行形態は3つです。

  • Embedded … テストケースと同じJavaVMで組み込みApacne Tomcatを起動してテスト
  • Managed … Arquillianがインストール済みのApache Tomcatを別プロセスとして起動してテスト
  • Remote … すでに起動済みのApache Tomcatに接続してテスト

それぞれ、設定に癖があったりします。

今回は以下を使用して簡単なアプリケーションを作成し、Arquillianでインテグレーションテストを書いてみたいと思います。

テストはJUnit 5、REST Assuredを使って書きます。

環境

今回の環境はこちら。

$ java --version
openjdk 21.0.7 2025-04-15
OpenJDK Runtime Environment (build 21.0.7+6-Ubuntu-0ubuntu124.04)
OpenJDK 64-Bit Server VM (build 21.0.7+6-Ubuntu-0ubuntu124.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.10 (5f519b97e944483d878815739f519b2eade0a91d)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 21.0.7, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-63-generic", arch: "amd64", family: "unix"

Apache Tomcatは10.1.43を使います。セットアップは後述します。

準備

Maven依存関係など。

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>jakarta.platform</groupId>
                <artifactId>jakarta.jakartaee-bom</artifactId>
                <version>10.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.enterprise</groupId>
            <artifactId>jakarta.enterprise.cdi-api</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.inject</groupId>
            <artifactId>jakarta.inject-api</artifactId>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-json-binding-provider</artifactId>
            <version>6.2.12.Final</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-cdi</artifactId>
            <version>6.2.12.Final</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-servlet-initializer</artifactId>
            <version>6.2.12.Final</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld.servlet</groupId>
            <artifactId>weld-servlet-core</artifactId>
            <version>5.1.6.Final</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.12.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.27.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.5.2</version>
            <scope>test</scope>
        </dependency>
        <!-- REST AssuredでJSONを扱うため-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit5</groupId>
            <artifactId>arquillian-junit5-container</artifactId>
            <version>1.9.3.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.shrinkwrap.resolver</groupId>
            <artifactId>shrinkwrap-resolver-depchain</artifactId>
            <version>3.3.4</version>
            <scope>test</scope>
            <type>pom</type>
        </dependency>
    </dependencies>

    <build>
        <finalName>ROOT</finalName>
    </build>

    <profiles>
        <!-- 後で -->
    </profiles>

後でArquillianの各実行形態ごとにプロファイルを作成します。

Arquillianに関する依存関係は、この時点では共通部分だけ入れています。

        <dependency>
            <groupId>org.jboss.arquillian.junit5</groupId>
            <artifactId>arquillian-junit5-container</artifactId>
            <version>1.9.3.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.shrinkwrap.resolver</groupId>
            <artifactId>shrinkwrap-resolver-depchain</artifactId>
            <version>3.3.4</version>
            <scope>test</scope>
            <type>pom</type>
        </dependency>

Arquillianのバージョンは、Apache Tomcat向け実装と同じものを指定しています。
※Arquillian自体にはもっと新しいバージョンがあります

https://github.com/arquillian/arquillian-container-tomcat/blob/1.2.3.Final/pom.xml#L35

Apache Tomcat向け実装を見ていてもJUnit 5が使えるかどうかよくわからなかったのですが、依存関係をよくよく見ると
特にJUnit 4に依存しているわけではなさそうだったので、Arquillian JUnit 5 Containerを入れてみたら問題なく動きました。

サンプルアプリケーション

テスト用のサンプルアプリケーションを作成しましょう。

JAX-RSの有効化。

src/main/java/org/littlewings/tomcat/arquillian/RestApplication.java

package org.littlewings.tomcat.arquillian;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/")
public class RestApplication extends Application {
}

JAX-RSリソースクラス。

src/main/java/org/littlewings/tomcat/arquillian/MessageResource.java

package org.littlewings.tomcat.arquillian;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import java.util.Map;

@ApplicationScoped
@Path("/message")
public class MessageResource {
    @Inject
    private MessageService messageService;

    @GET
    public String get(@QueryParam("word") String word) {
        return messageService.message(word);
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> post(Map<String, Object> request) {
        return Map.of("message", messageService.message((String) request.get("word")));
    }
}

CDI管理Bean。

src/main/java/org/littlewings/tomcat/arquillian/MessageService.java

package org.littlewings.tomcat.arquillian;

import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class MessageService {
    public String message(String word) {
        return String.format("Hello %s!!", word != null ? word : "World");
    }
}

CDIの有効化。

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




Apache Tomcatへのデプロイは省略しますが、動作確認するとこんな感じです。

$ curl localhost:8080/message
Hello World!!


$ curl localhost:8080/message?word=Arquillian
Hello Arquillian!!


$ curl localhost:8080/message --json '{}'
{"message":"Hello World!!"}


$ curl localhost:8080/message --json '{"word": "Arquillian"}'
{"message":"Hello Arquillian!!"}

これで、準備は完了ですね。

ArquillianとApache Tomcatでテストする

それでは、Arquillianを使ってテストをしていきましょう。

こういう感じで載せていきます。

  • Apache Tomcatのインストール
  • テストコードの作成
  • Managedでの実行
  • Remoteでの実行
Apache Tomcatのインストール

それでは、Apache Tomcatのインストールをしていきます。

ダウンロードして展開するだけでは?と思いきや、少し追加があります。

$ curl -LO https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.43/bin/apache-tomcat-10.1.43.tar.gz
$ tar xf apache-tomcat-10.1.43.tar.gz
$ cd apache-tomcat-10.1.43

ダウンロードしたら、不要なアプリケーションを削除しておきましょう。

$ rm -rf webapps/{ROOT,docs,examples,host-manager}

Managed、Remote共通ですがmanagerアプリケーションが必要になります

$ ll webapps
合計 12
drwxr-x--- 3 xxxxx xxxxx 4096  7月  6 14:19 ./
drwxrwxr-x 9 xxxxx xxxxx 4096  7月  6 14:19 ../
drwxr-x--- 6 xxxxx xxxxx 4096  7月  6 14:19 manager/

次に、conf/tomcat-users.xmlを修正します。

デフォルトでは以下のようにコメントアウトされていると思いますが、

<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->

manager-scriptロールを持つユーザーを作成します。

  <user username="arquillian" password="password" roles="manager-script"/>

これは、Managed、Remoteの両方で必要な設定です。

Username of the user who has manager-script role. It is set in $CATALINA_HOME/conf/tomcat-users.xml.

Arquillian - Tomcat Containers / Tomcat Managed / Configuration / Container Configuration Options

The user to authenticate as when using the Management console.

Arquillian - Tomcat Containers / Tomcat Remote / Configuration / Container Configuration Options

https://github.com/arquillian/arquillian-container-tomcat/commit/934b18facb7320e669e00893099febc139da2075

ところで、今はREADME.adocに設定が書かれているのですが、1.2.3.Final(今回使っているバージョン)のリリース時点では
ドキュメントってなかったんですね…。

https://github.com/arquillian/arquillian-container-tomcat/blob/1.2.3.Final/README.md

Apache Tomcatの準備はいったんここでおしまいです。

Remoteで使う時は、追加の設定が必要になります。

テストコードの作成

続いて、Arquillianを使ったテストコードの作成。JUnit 5で書きます。

CDI管理Beanのテスト。

src/test/java/org/littlewings/tomcat/arquillian/MessageServiceTest.java

package org.littlewings.tomcat.arquillian;

import jakarta.inject.Inject;
import java.io.File;
import java.nio.file.Path;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit5.ArquillianExtension;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(ArquillianExtension.class)
class MessageServiceTest {
    @Deployment
    static WebArchive createDeployment() {
        File[] compileAndRuntimeScopeDependencyFiles =
                Maven
                        .resolver()
                        .loadPomFromFile("pom.xml")
                        .importCompileAndRuntimeDependencies()
                        .resolve()
                        .withTransitivity()
                        .asFile();

        File mainResources = Path.of("src/main/resources").toFile();

        return ShrinkWrap
                .create(WebArchive.class)
                .addPackages(true, RestApplication.class.getPackage())
                .addAsResource(mainResources, "")
                .addAsLibraries(compileAndRuntimeScopeDependencyFiles)
                .addAsLibraries(
                        Maven
                                .resolver()
                                .resolve("org.assertj:assertj-core:3.27.3")
                                .withTransitivity()
                                .asFile()
                );
    }

    @Inject
    private MessageService messageService;

    @Test
    void test() {
        assertThat(messageService.message(null))
                .isEqualTo("Hello World!!");

        assertThat(messageService.message("Arquillian"))
                .isEqualTo("Hello Arquillian!!");
    }
}

JAX-RSリソースクラスのテスト。こちらはクライアントとして動作させ、REST Assuredを使います。

src/test/java/org/littlewings/tomcat/arquillian/MessageResourceTest.java

package org.littlewings.tomcat.arquillian;

import io.restassured.common.mapper.TypeRef;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import java.io.File;
import java.net.URL;
import java.nio.file.Path;
import java.util.Map;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit5.ArquillianExtension;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;

@ExtendWith(ArquillianExtension.class)
@RunAsClient
class MessageResourceTest {
    @Deployment
    static WebArchive createDeployment() {
        File[] compileAndRuntimeScopeDependencyFiles =
                Maven
                        .resolver()
                        .loadPomFromFile("pom.xml")
                        .importCompileAndRuntimeDependencies()
                        .resolve()
                        .withTransitivity()
                        .asFile();

        File mainResources = Path.of("src/main/resources").toFile();

        return ShrinkWrap
                .create(WebArchive.class)
                .addPackages(true, RestApplication.class.getPackage())
                .addAsResource(mainResources, "")
                .addAsLibraries(compileAndRuntimeScopeDependencyFiles)
                .addAsLibraries(
                        Maven
                                .resolver()
                                .resolve("org.assertj:assertj-core:3.27.3")
                                .withTransitivity()
                                .asFile()
                );
    }

    @ArquillianResource
    private URL deploymentUrl;

    String resourcePrefix =
            RestApplication.class
                    .getAnnotation(ApplicationPath.class)
                    .value()
                    .replaceFirst("^/", "");

    @Test
    void get() {
        given()
                .when()
                .get(String.format("%s%s%s", deploymentUrl, resourcePrefix, "message"))
                .then()
                .assertThat()
                .statusCode(200)
                .body(is("Hello World!!"));

        given()
                .queryParam("word", "Arquillian")
                .when()
                .get(String.format("%s%s%s", deploymentUrl, resourcePrefix, "message"))
                .then()
                .assertThat()
                .statusCode(200)
                .body(is("Hello Arquillian!!"));
    }

    @Test
    void post() {
        Map<String, Object> response1 =
                given()
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
                        .body(Map.of())
                        .when()
                        .post(String.format("%s%s%s", deploymentUrl, resourcePrefix, "message"))
                        .then()
                        .assertThat()
                        .statusCode(200)
                        .extract()
                        .as(new TypeRef<>() {
                        });
        assertThat(response1).isEqualTo(Map.of("message", "Hello World!!"));

        Map<String, Object> response2 =
                given()
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
                        .body(Map.of("word", "Arquillian"))
                        .when()
                        .post(String.format("%s%s%s", deploymentUrl, resourcePrefix, "message"))
                        .then()
                        .assertThat()
                        .statusCode(200)
                        .extract()
                        .as(new TypeRef<Map<String, Object>>() {
                        });
        assertThat(response2).isEqualTo(Map.of("message", "Hello Arquillian!!"));
    }
}

Arquillianの設定は、Managed、Remoteでそれぞれ以下のようにしています。

src/test/resources/arquillian.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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="tomcat-managed" default="true">
        <configuration>
            <property name="catalinaHome">${installed.catalina.home}</property>
            <property name="user">arquillian</property>
            <property name="pass">password</property>
        </configuration>
    </container>
    <container qualifier="tomcat-remote">
        <configuration>
            <property name="user">arquillian</property>
            <property name="pass">password</property>
        </configuration>
    </container>
</arquillian>

どのコンテナーの設定を使うかは、Maven Surefire Pluginでシステムプロティーを使って切り替えることにします。

Managed

まずはManagedから動かしていきましょう。

Managed用のプロファイルは以下のように定義しました。

    <profiles>
        <profile>
            <id>managed</id>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.arquillian.container</groupId>
                    <artifactId>arquillian-tomcat-managed-10</artifactId>
                    <version>1.2.3.Final</version>
                    <scope>test</scope>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>3.5.3</version>
                        <configuration>
                            <systemPropertyVariables>
                                <arquillian.container>tomcat-managed</arquillian.container>
                                <installed.catalina.home>/path/to/apache-tomcat-10.1.43</installed.catalina.home>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        〜省略〜

    </profiles>

Managed用のArquillianの依存関係はこちらですね。

                <dependency>
                    <groupId>org.jboss.arquillian.container</groupId>
                    <artifactId>arquillian-tomcat-managed-10</artifactId>
                    <version>1.2.3.Final</version>
                    <scope>test</scope>
                </dependency>

Arquillianの設定は、以下のように指定しています。

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>3.5.3</version>
                        <configuration>
                            <systemPropertyVariables>
                                <arquillian.container>tomcat-managed</arquillian.container>
                                <installed.catalina.home>/path/to/apache-tomcat-10.1.43</installed.catalina.home>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>

arquillian.containerarquillian.xmlqualifierの切り替え、Apache Tomcatのインストールディレクトリーはプロパティで
指定するようにしていたのでそちらを埋めています。

    <container qualifier="tomcat-managed" default="true">
        <configuration>
            <property name="catalinaHome">${installed.catalina.home}</property>
            <property name="user">arquillian</property>
            <property name="pass">password</property>
        </configuration>
    </container>

あとはテストをすればOKです。

$ mvn -P managed test

テストを実行すると、Apache Tomcatを起動してテストを行い、終わったらApache Tomcatを停止します。

[INFO] Results:
[INFO]
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
Remote

最後はRemoteです。

Remoteの場合は、Apache Tomcatに追加設定が必要です。JMX Remoteを使う必要があるので、ドキュメントに習って以下のように
設定します。

bin/setenv.sh

#!/bin/bash

CATALINA_OPTS='-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false'

Managedの時にはなかった設定のように見えますが、これはManagedの時はArquillian側で追加するので意識していないだけですね。

https://github.com/arquillian/arquillian-container-tomcat/blob/1.2.3.Final/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainer.java#L137-L139

Remote用のプロファイルは以下のように定義しました。

    <profiles>

        〜省略〜

        <profile>
            <id>remote</id>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.arquillian.container</groupId>
                    <artifactId>arquillian-tomcat-remote-10</artifactId>
                    <version>1.2.3.Final</version>
                    <scope>test</scope>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>3.5.3</version>
                        <configuration>
                            <systemPropertyVariables>
                                <arquillian.container>tomcat-remote</arquillian.container>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        〜省略〜

    </profiles>

Remote用のArquillianの依存関係はこちらですね。

                <dependency>
                    <groupId>org.jboss.arquillian.container</groupId>
                    <artifactId>arquillian-tomcat-remote-10</artifactId>
                    <version>1.2.3.Final</version>
                    <scope>test</scope>
                </dependency>

Arquillianの設定を切り替えているのはこちら。

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>3.5.3</version>
                        <configuration>
                            <systemPropertyVariables>
                                <arquillian.container>tomcat-remote</arquillian.container>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>

qualifierで指定したコンテナーを使うように切り替えているだけですね。

    <container qualifier="tomcat-remote">
        <configuration>
            <property name="user">arquillian</property>
            <property name="pass">password</property>
        </configuration>
    </container>

Remoteの場合は、先にApache Tomcatを起動しておく必要があります。

$ bin/startup.sh

あとはテストを実行します。

$ mvn -P remote test

OKですね。

[INFO] Results:
[INFO]
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

ちなみに、JMX Remoteの設定を行っていなかった場合は以下のように例外がスローされます。

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.292 s <<< FAILURE! -- in org.littlewings.tomcat.arquillian.MessageServiceTest
[ERROR] org.littlewings.tomcat.arquillian.MessageServiceTest -- Time elapsed: 2.292 s <<< ERROR!
org.jboss.arquillian.container.spi.client.container.DeploymentException:
Unable to contruct metadata for archive deployment.
Can't connect to 'service:jmx:rmi:///jndi/rmi://localhost:8089/jmxrmi'.
   Make sure JMX remote acces is enabled Tomcat's JVM - e.g. in startup.sh using $JAVA_OPTS.
   Example (with no authentication):
     -Dcom.sun.management.jmxremote.port=8089
     -Dcom.sun.management.jmxremote.ssl=false
     -Dcom.sun.management.jmxremote.authenticate=false
        at org.jboss.arquillian.container.tomcat.ProtocolMetadataParser.retrieveContextServletInfo(ProtocolMetadataParser.java:81)
        at org.jboss.arquillian.container.tomcat.remote.TomcatRemoteContainer.deploy(TomcatRemoteContainer.java:113)
        at org.jboss.arquillian.container.tomcat.remote.Tomcat10RemoteContainer.deploy(Tomcat10RemoteContainer.java:30)
        at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:151)
        at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:118)
        at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.executeOperation(ContainerDeployController.java:239)
        at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.deploy(ContainerDeployController.java:118)

〜省略〜

オマケ: Embedded

最後に、動かせませでしたがEmbeddedも載せておきます。

Embedded用のプロファイルの定義。

        <profile>
            <id>embedded</id>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.arquillian.container</groupId>
                    <artifactId>arquillian-tomcat-embedded-10</artifactId>
                    <version>1.2.3.Final</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-core</artifactId>
                    <version>10.1.43</version>
                    <scope>provided</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-jasper</artifactId>
                    <version>10.1.43</version>
                    <scope>provided</scope>
                </dependency>
                <dependency>
                    <groupId>org.eclipse.jdt.core.compiler</groupId>
                    <artifactId>ecj</artifactId>
                    <version>3.7</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.jboss.weld.servlet</groupId>
                    <artifactId>weld-servlet-core</artifactId>
                    <version>5.1.6.Final</version>
                    <scope>test</scope>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>3.5.3</version>
                        <configuration>
                            <systemPropertyVariables>
                                <arquillian.container>tomcat-embedded</arquillian.container>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

arquillian.xmlには、以下のコンテナー定義があるものとします。

    <container qualifier="tomcat-embedded">
        <configuration>
            <property name="unpackArchive">true</property>
        </configuration>
    </container>

これでテストを実行すると

$ mvn -P embedded test

以下のようにCDI管理Beanが2つあるように認識されてうまく動きませんでした…。

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type MessageService with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private org.littlewings.tomcat.arquillian.MessageResource.messageService
  at org.littlewings.tomcat.arquillian.MessageResource.messageService(MessageResource.java:0)
  Possible dependencies:
  - Managed Bean [class org.littlewings.tomcat.arquillian.MessageService] with qualifiers [@Any @Default],
  - Managed Bean [class org.littlewings.tomcat.arquillian.MessageService] with qualifiers [@Any @Default]

        at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:387)
        at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:294)
        at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:141)
        at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:163)
        at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:533)
        at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:65)
        at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:63)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)

〜省略〜

おわりに

Apache Tomcat 10.1、Arquillian、JUnit 5でインテグレーションテストを書いてみました。情報がなかなかつながらず
ややハマりましたが、ドキュメントもできていたので最終的にはなんとかなりました。

ManagedとRemoteのみを扱いましたが、ふだん使うならこのどちらかかなと思うのでまあいいでしょう。

ただ、やっぱりテストとしてはちょっと重たいですね…。




以上の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/07/06/211629より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14