1. 概要

MavenはJavaスペースで最も人気のあるビルドツールですが、統合テストは開発プロセスの重要な部分です。 したがって、Mavenとの統合テストを構成して実行するのは自然な選択です。

このチュートリアルでは、統合テストにMavenを使用し、統合テストを単体テストから分離するためのさまざまな方法について説明します。

2. 準備

デモコードを実際のプロジェクトに近づけるために、JAX-RSアプリケーションをセットアップします。 このアプリケーションは、統合テストの実行前にサーバーにデプロイされ、後で解体されます。

2.1. Maven構成

JAX-RSのリファレンス実装であるJerseyを中心にRESTアプリケーションを構築します。 この実装には、いくつかの依存関係が必要です。

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.27</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.27</version>
</dependency>

これらの依存関係の最新バージョンは、ここおよびここにあります。

JettyMavenプラグインを使用してテスト環境をセットアップします。 このプラグインは、Mavenビルドライフサイクルの統合テスト前のフェーズでJettyサーバーを起動し、統合テスト後のフェーズで停止します。

pom.xmlでJettyMavenプラグインを構成する方法は次のとおりです。

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.4.11.v20180605</version>
    <configuration>
        <httpConnector>
            <port>8999</port>
        </httpConnector>
        <stopKey>quit</stopKey>
        <stopPort>9000</stopPort>
    </configuration>
    <executions>
        <execution>
            <id>start-jetty</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>stop-jetty</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Jettyサーバーが起動すると、ポート8999でリッスンします。 stopKeyおよびstopPort構成要素は、プラグインの stop 目標によってのみ使用され、それらの値は私たちの観点からは重要ではありません。

ここは、JettyMavenプラグインの最新バージョンを見つける場所です。

もう1つの注意点は、pom.xmlファイルのpackaging要素をwarに設定する必要があることです。そうしないと、Jettyプラグインがサーバーを起動できません。

<packaging>war</packaging>

2.2. RESTアプリケーションの作成

アプリケーションエンドポイントは非常に単純です。GETリクエストがコンテキストルートに到達すると、ウェルカムメッセージが返されます。

@Path("/")
public class RestEndpoint {
    @GET
    public String hello() {
        return "Welcome to Baeldung!";
    }
}

エンドポイントクラスをJerseyに登録する方法は次のとおりです。

package com.baeldung.maven.it;

import org.glassfish.jersey.server.ResourceConfig;

public class EndpointConfig extends ResourceConfig {
    public EndpointConfig() {
        register(RestEndpoint.class);
    }
}

JettyサーバーにRESTアプリケーションを認識させるために、従来のweb.xmlデプロイメント記述子を使用できます。

<web-app 
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">
    <servlet>
        <servlet-name>rest-servlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.baeldung.maven.it.EndpointConfig</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>rest-servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

この記述子は、サーバーによって認識されるように/ src / main / webapp /WEB-INFディレクトリに配置する必要があります。

2.3. クライアント側のテストコード

次のセクションのすべてのテストクラスには、単一のメソッドが含まれています。

@Test
public void whenSendingGet_thenMessageIsReturned() throws IOException {
    String url = "http://localhost:8999";
    URLConnection connection = new URL(url).openConnection();
    try (InputStream response = connection.getInputStream();
      Scanner scanner = new Scanner(response)) {
        String responseBody = scanner.nextLine();
        assertEquals("Welcome to Baeldung!", responseBody);
    }
}

ご覧のとおり、このメソッドは、前に設定したWebアプリケーションにGETリクエストを送信し、応答を確認するだけです。

3. 実行中の統合テスト

統合テストについて注意すべき重要な点は、テストメソッドの実行に非常に長い時間がかかることが多いことです。

結果として、統合テストをデフォルトのビルドライフサイクルから除外し、プロジェクトをビルドするたびにプロセス全体の速度が低下しないようにする必要があります。

統合テストを分離する便利な方法は、ビルドプロファイルを使用することです。この種の構成では、適切なプロファイルを指定することにより、必要な場合にのみ統合テストを実行できます。

次のセクションでは、ビルドプロファイルを使用してすべての統合テストを構成します。

4. フェイルセーフプラグインを使用したテスト

統合テストを実行する最も簡単な方法は、Mavenフェイルセーフプラグインを使用することです。

デフォルトでは、Maven surefireプラグインはtest フェーズで単体テストを実行し、failsafeプラグインは統合テストフェーズで統合テストを実行します。

これらのプラグインのパターンが異なるテストクラスに名前を付けて、同封のテストを個別に取得できます。

surefirefailsafeによって適用されるデフォルトの命名規則は異なるため、ユニットテストと統合テストを分離するには、これらの規則に従う必要があります。

surefire プラグインの実行には、名前が Test で始まるか、 Test Tests 、またはTestCaseで終わるすべてのクラスが含まれます。 。 対照的に、 failsafe プラグインは、名前が IT で始まるか、ITまたはITCaseで終わるクラスでテストメソッドを実行します。

このシュアファイアのテストインクルージョンに関するドキュメントを見つけることができ、ここフェイルセーフのドキュメントです。

failsafeプラグインをデフォルト構成でPOMに追加しましょう。

<profile>
    <id>failsafe</id>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

このリンクは、failsafeプラグインの最新バージョンを見つける場所です。

上記の構成では、統合テストフェーズで次のテストメソッドが実行されます。

public class RestIT {
    // test method shown in subsection 2.3
}

Jettyサーバーはpre-integration-testフェーズで起動し、 post-integration-test でシャットダウンするため、今見たテストは次のコマンドで合格します。

mvn verify -Pfailsafe

命名パターンをカスタマイズして、異なる名前のクラスを含めることもできます。

<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.22.0</version>
    <configuration>
        <includes>
            <include>**/*RestIT</include>
            <include>**/RestITCase</include>
        </includes>
    </configuration>
    ...
</plugin>

5. Surefireプラグインを使用したテスト

failsafe プラグインとは別に、 surefireプラグインを使用して、さまざまなフェーズでユニットテストと統合テストを実行することもできます。

すべての統合テストにIntegrationTestという接尾辞を付けて名前を付けたいとしましょう。 surefire プラグインは、デフォルトで test フェーズでそのような名前のテストを実行するため、デフォルトの実行からそれらを除外する必要があります。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <excludes>
            <exclude>**/*IntegrationTest</exclude>
        </excludes>
    </configuration>
</plugin>

このプラグインの最新バージョンはこちらです。

名前がIntegrationTestで終わるすべてのテストクラスを、ビルドライフサイクルから除外しました。 プロファイルを使用してそれらを元に戻す時が来ました:

<profile>
    <id>surefire</id>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <executions>
                    <execution>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <excludes>
                                <exclude>none</exclude>
                            </excludes>
                            <includes>
                                <include>**/*IntegrationTest</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

surefireプラグインのテスト目標をテストビルドフェーズにバインドする代わりに、通常どおり、統合テストフェーズにバインドします。プラグインは統合テストプロセス中に起動します。

基本構成で指定された除外をオーバーライドするには、exclude要素をnoneに設定する必要があることに注意してください。

それでは、名前付けパターンを使用して統合テストクラスを定義しましょう。

public class RestIntegrationTest {
    // test method shown in subsection 2.3
}

このテストは、次のコマンドで実行されます。

mvn verify -Psurefire

6. Cargoプラグインを使用したテスト

surefireプラグインをMavencargoプラグインと一緒に使用できます。 このプラグインには、統合テストに非常に役立つ組み込みサーバーのサポートが組み込まれています。

この組み合わせの詳細については、こちらをご覧ください。

7. JUnitの@Categoryを使用したテスト

テストを選択的に実行する便利な方法は、JUnit4フレームワークの@Categoryアノテーションを活用することです。 このアノテーションを使用すると、特定のテストを単体テストから除外し、統合テストに含めることができます。

まず、カテゴリ識別子として機能するインターフェイスまたはクラスが必要です。

package com.baeldung.maven.it;

public interface Integration { }

次に、@CategoryアノテーションとIntegration識別子を使用してテストクラスを装飾できます。

@Category(Integration.class)
public class RestJUnitTest {
    // test method shown in subsection 2.3
}

テストクラスで@Categoryアノテーションを宣言するのではなく、メソッドレベルで使用して、個々のテストメソッドを分類することもできます。

テストビルドフェーズからカテゴリを除外するのは簡単です。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <excludedGroups>com.baeldung.maven.it.Integration</excludedGroups>
    </configuration>
</plugin>

Integrationカテゴリをintegration-testフェーズに含めることも簡単です。

<profile>
    <id>category</id>
        <build>
        <plugins>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.0</version>
                <configuration>
                    <includes>
                        <include>**/*</include>
                    </includes>
                    <groups>com.baeldung.maven.it.Integration</groups>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

これで、Mavenコマンドを使用して統合テストを実行できます。

mvn verify -Pcategory

8. 統合テスト用に別のディレクトリを追加する

統合テスト用に別のディレクトリを用意することが望ましい場合があります。 このようにテストを整理すると、統合テストを単体テストから完全に分離できます。

この目的のために、Mavenビルドヘルパープラグインを使用できます。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>add-integration-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/integration-test/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

ここは、このプラグインの最新バージョンを見つけることができる場所です。

今見た構成では、テストソースディレクトリがビルドに追加されます。 その新しいディレクトリにクラス定義を追加しましょう。

public class RestITCase {
    // test method shown in subsection 2.3
}

このクラスで統合テストを実行するときが来ました。

mvn verify -Pfailsafe

Maven failsafe プラグインは、サブセクション3.1で設定した構成により、このテストクラスのメソッドを実行します。

多くの場合、テストソースディレクトリはリソースディレクトリと一緒に使用されます。 このようなディレクトリを別のexecution要素のプラグイン構成に追加できます。

<executions>
    ...
    <execution>
        <id>add-integration-test-resource</id>
        <phase>generate-test-resources</phase>
        <goals>
            <goal>add-test-resource</goal>
        </goals>
        <configuration>
            <resources>
                <resource>
                    <directory>src/integration-test/resources</directory>
                </resource>
            </resources>
        </configuration>
    </execution>
</executions>

9. 結論

この記事では、Mavenを使用してJettyサーバーとの統合テストを実行し、Maven surefireおよびfailsafeプラグインの構成に焦点を当てました。

このチュートリアルの完全なソースコードは、GitHubにあります。