Quarkus アプリケーションのテスト
はじめに
アプリケーション開発者は、Red Hat ビルドの Quarkus を使用して、OpenShift 環境およびサーバーレス環境で実行される Java で書かれたマイクロサービスベースのアプリケーションを作成できます。ネイティブ実行可能ファイルにコンパイルされたアプリケーションは、メモリーのフットプリントが小さく、起動時間は高速です。
本ガイドでは、Apache Maven を使用して JVM モードで Quarkus Getting Started プロジェクトをテストする方法と、リソースをテストにインジェクトする方法を説明します。Quarkus スタートガイド で作成したテストを展開します。
このチュートリアルで使用する Quarkus Maven プロジェクトを Quarkus quickstart archive からダウンロードしたり、Quarkus Quickstarts
Git リポジトリーをクローンしたりすることもできます。この演習は getting-started-testing
ディレクトリーにあります。
前提条件
OpenJDK (JDK) 11 がインストールされ、
JAVA_HOME
環境変数が Java SDK の場所を指定している。- Red Hat ビルドの Open JDK は、Red Hat カスタマーポータルの Software Downloads ページからダウンロードできます (ログインが必要です)。
Apache Maven 3.8.1 以降がインストールされている。
- Maven は Apache Maven Project の Web サイトからダウンロードできます。
Quarkus Getting Started プロジェクトを完了している。
- Quarkus Getting Started プロジェクトのビルド方法は、Quarkus スタートガイド を参照してください。
-
あるいは、Quarkus quickstart archive をダウンロードするか、
Quarkus Quickstarts
Git リポジトリーをクローンしてください。この例はgetting-started
ディレクトリーにあります。
Red Hat ドキュメントへのフィードバック (英語のみ)
弊社の技術的な内容についてのフィードバックに感謝します。ご意見をお聞かせください。コメントの追加、Insights の提供、誤字の修正、および質問を行う必要がある場合は、ドキュメントで直接行うこともできます。
Red Hat アカウントがあり、カスタマーポータルにログインしている必要があります。
カスタマーポータルからドキュメントのフィードバックを送信するには、以下の手順を実施します。
- Multi-page HTML 形式を選択します。
- ドキュメントの右上にある Feedback ボタンをクリックします。
- フィードバックを提供するテキストのセクションを強調表示します。
- ハイライトされたテキストの横にある Add Feedback ダイアログをクリックします。
- ページの右側のテキストボックスにフィードバックを入力し、Submit をクリックします。
フィードバックを送信すると、自動的に問題の追跡が作成されます。Submit をクリックすると表示されるリンクを開き、問題の監視を開始するか、さらにコメントを追加します。
貴重なフィードバックにご協力いただきありがとうございます。
多様性を受け入れるオープンソースの強化
Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。まずは、マスター (master)、スレーブ (slave)、ブラックリスト (blacklist)、ホワイトリスト (whitelist) の 4 つの用語の置き換えから始めます。この取り組みは膨大な作業を要するため、今後の複数のリリースで段階的に用語の置き換えを実施して参ります。詳細は、Red Hat CTO である Chris Wright のメッセージ をご覧ください。
第1章 テスト依存関係の確認
このチュートリアルでは、Quarkus Getting Started プロジェクトが完了済みで、プロジェクト pom.xml
ファイルに quarkus-junit5
および rest-assured
依存関係が含まれている必要があります。Quarkus Getting Started の演習を完了した場合、または完了済みのサンプルをダウンロードした場合に、これらの依存関係が表示されます。
-
quarkus-junit5
依存関係は、テストフレームワークを制御する@QuarkusTest
アノテーションを提供するため、テストに必要です。 rest-assured
依存関係は必要ありませんが、HTTP エンドポイントをテストするための便利な方法として使用できます。注記Quarkus は正しい URL を自動的に設定するインテグレーションを提供するため、設定は必要ありません。
手順
-
Getting Started プロジェクトの
pom.xml
ファイルを開きます。 以下の依存関係がファイルに含まれていることを確認し、必要な場合は追加します。
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency>
pom.xml
ファイルにmaven-surefire-plugin
が含まれることを確認します。このチュートリアルでは JUnit 5 フレームワークを使用することから、maven-surefire-plugin
のバージョンを設定する必要があります (デフォルトのバージョンでは JUnit 5 に対応していないため)。<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>${surefire-plugin.version}</version> <configuration> <systemProperties> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> </systemProperties> </configuration> </plugin>
-
テスト用に適切なログマネージャーを使用するように、
java.util.logging.manager
システムプロパティーを設定します。 GreetingResourceTest.java
ファイルに以下の内容が含まれていることを確認し、必要な場合は追加します。package org.acme.quickstart; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; import java.util.UUID; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; @QuarkusTest public class GreetingResourceTest { @Test public void testHelloEndpoint() { given() .when().get("/hello") .then() .statusCode(200) .body(is("hello")); } @Test public void testGreetingEndpoint() { String uuid = UUID.randomUUID().toString(); given() .pathParam("name", uuid) .when().get("/hello/greeting/{name}") .then() .statusCode(200) .body(is("hello " + uuid)); } }
テストを実行するには、以下のコマンドを入力します。
./mvnw clean verify
IDE から直接テストを実行することもできます。
このテストでは、HTTP を使用して REST エンドポイントを直接テストします。テストがトリガーされると、テストの実行前にアプリケーションが起動します。
第2章 テストポートの指定
デフォルトでは、Quarkus テストはポート 8081
で実行され、実行中のアプリケーションとの競合が発生しないようにします。これにより、アプリケーションを並行して実行中にテストを実行できます。application.properties
ファイルで、テスト接続に別のポートを指定できます。別のポートを使用して、セキュアでない HTTP 接続と SSL でセキュア化された接続をテストできます。
手順
application.properties
ファイルでquarkus.http.test-port
プロパティーおよびquarkus.http.test-ssl-port
プロパティーを設定します。<port>
を、テスト接続に使用するポートの数に置き換えます。quarkus.http.test-port=<port> quarkus.http.test-ssl-port=<port>
ポート番号を
0
に設定すると、オペレーティングシステムは、システムで利用可能なポートの範囲からランダムなポートを割り当てることができます。注記Quarkus は、テストの実行前に Rest Assured が使用するデフォルトポートを更新する Rest Assured インテグレーションを提供するため、追加の設定は必要ありません。
第3章 HTTP テスト接続のレスポンスタイムアウトの期間の設定
REST Assured を使用してアプリケーションの REST API をテストする場合、デフォルトの接続およびレスポンスタイムアウトの期間は 30 秒に設定されます。アプリケーションのタイムアウト期間の長さを変更することができます。
手順
-
アプリケーションプロジェクトで
application.properties
ファイルを開きます。 quarkus.http.test-timeout
プロパティーの値をタイムアウト期間として設定したい期間の長さに設定し、続いてその期間の時間の単位を設定します。application.properties
quarkus.http.test-timeout=<duration>
たとえば、レスポンスタイムアウトの期間の長さを 10 秒に設定するには、以下を実行します。
application.properties
quarkus.http.test-timeout=10s
第4章 テストへの URL の注入
別のクライアントを使用する場合は、Quarkus @TestHTTPResource
アノテーションを使用して、テスト予定のアプリケーションの URL を test クラスのフィールドに直接注入します。このフィールドには、タイプ String
、URL
、または URI
を使用できます。このアノテーションにテストパスを指定することもできます。この演習では、静的リソースをロードする簡単なテストを作成します。
手順
以下の内容を含む
src/main/resources/META-INF/resources/index.html
ファイルを作成します。<html> <head> <title>Testing Guide</title> </head> <body> Information about testing </body> </html>
以下の内容で
StaticContentTest.java
ファイルを作成し、index.html
に適切なサービスが提供されていることをテストします。package org.acme.quickstart; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import io.quarkus.test.common.http.TestHTTPResource; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest public class StaticContentTest { @TestHTTPResource("index.html") 1 URL url; @Test public void testIndexHtml() throws Exception { try (InputStream in = url.openStream()) { String contents = readStream(in); Assertions.assertTrue(contents.contains("<title>Testing Guide</title>")); } } private static String readStream(InputStream in) throws IOException { byte[] data = new byte[1024]; int r; ByteArrayOutputStream out = new ByteArrayOutputStream(); while ((r = in.read(data)) > 0) { out.write(data, 0, r); } return new String(out.toByteArray(), StandardCharsets.UTF_8); } }
- 1
@TestHTTPResource
アノテーションを使用すると、Quarkus インスタンスの URL を直接注入できます。アノテーションの値は URL の path コンポーネントです。
第5章 CDI Bean のテストへの注入
ユニットテストを実行し、CDI Bean を直接テストできます。Quarkus により、@Inject
アノテーションを使用して CDI Bean をテストに注入できます。実際、Quarkus のテストでは完全な CDI Bean であるため、完全な CDI 機能を使用できます。
ネイティブテストで注入を使用することはできません。
手順
次の内容で
GreetingServiceTest.java
ファイルを作成します。package org.acme.quickstart; import javax.inject.Inject; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest public class GreetingServiceTest { @Inject 1 GreetingService service; @Test public void testGreetingService() { Assertions.assertEquals("hello Quarkus", service.greeting("Quarkus")); } }
- 1
GreetingService
Bean はテストに注入されます。
第6章 テストへのインターセプターの適用
Quarkus テストは完全な CDI Bean であるため、通常通りに CDI インターセプターを適用できます。たとえば、トランザクションのコンテキスト内であるテスト方法を実行する場合は、@Transactional
アノテーションをその方法に適用できます。また、独自のテストステレオタイプを作成することもできます。
手順
quarkus-narayana-jta
依存関係をpom.xml
ファイルに追加します。<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-narayana-jta</artifactId> </dependency>
TransactionalQuarkusTest.java
に、以下の import ステートメントが含まれていることを確認してください。package org.acme.quickstart; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.enterprise.inject.Stereotype; import javax.transaction.Transactional; import io.quarkus.test.junit.QuarkusTest;
@TransactionalQuarkusTest
アノテーションを作成します。@QuarkusTest @Stereotype @Transactional @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TransactionalQuarkusTest { }
このアノテーションを、
@QuarkusTest
アノテーションおよび@Transactional
アノテーションの両方を適用したかのように動作するテストクラスに適用します。@TransactionalQuarkusTest public class TestStereotypeTestCase { @Inject UserTransaction userTransaction; @Test public void testUserTransaction() throws Exception { Assertions.assertEquals(Status.STATUS_ACTIVE, userTransaction.getStatus()); } }
これは、HTTP を使用せずに greeting サービスを直接評価する簡単なテストです。
第7章 CDI Bean のモック化
Quarkus により、特定のテスト用に一部の CDI Bean をモック化できます。
以下の方法の 1 つを使用して、オブジェクトをモック化できます。
-
src/test/java
ディレクトリーのクラスでモック化する Bean を上書きし、@Alternative
および@Priority(1)
のアノテーションを Bean に配置します。 -
io.quarkus.test.Mock
ステレオタイプアノテーションを使用します。@Mock
アノテーションには、@Alternative
、@Priority(1)
、および@Dependent
アノテーションが含まれます。
以下の手順では、@Alternative
アノテーションを使用して外部サービスをモック化する方法を説明します。ネイティブイメージには代替のテストが含まれていないため、この方法はネイティブイメージテストでは機能しない点に留意してください。
手順
次の例のように、
src/main/java
ディレクトリーにExternalService
を作成します。package org.acme.quickstart; import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class ExternalService { public String service() { return "external"; } }
src/main/java
ディレクトリーでExternalService
を使用するクラスUsesExternalService
を作成します。package org.acme.quickstart; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @ApplicationScoped public class UsesExternalService { @Inject ExternalService externalService; public String doSomething() { return externalService.service(); } }
以下の例に示すような
src/test/java
ディレクトリーにテストを作成します。package org.acme.quickstart; import javax.inject.Inject; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @QuarkusTest class UsesExternalServiceTest { @Inject UsesExternalService usesExternalService; @Test public void testDoSomething() { Assertions.assertEquals("external", usesExternalService.doSomething()); } }
@Alternative
アノテーションを使用するsrc/test/java
にMockExternalService
を作成します。package org.acme.quickstart; import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Alternative; @Alternative @Priority(1) @ApplicationScoped public class MockExternalService extends ExternalService { 1 @Override public String service() { return "mock"; } }
- 1
MockExternalService
は、ExternalService
が使用されている場所に注入されます。この例では、MockExternalService
がUsesExternalService
で使用されます。
注記@Alternative
、@Priority(1)
、および@Dependent
アノテーションの代わりに@Mock
アノテーションを使用できます。以下の例は、
@Mock
アノテーションを使用するMockExternalService
クラスを作成する方法を示しています。import javax.enterprise.context.ApplicationScoped; import io.quarkus.test.Mock; @Mock @ApplicationScoped public class MockExternalService extends ExternalService { @Override public String service() { return "mock"; } }
テストで、アサートされた文字列を
"external"
から"mock"
に変更します。package org.acme.quickstart; import javax.inject.Inject; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @QuarkusTest class UsesExternalServiceTest { @Inject UsesExternalService usesExternalService; @Test public void testDoSomething() { Assertions.assertEquals("mock", usesExternalService.doSomething()); } }
第8章 関連情報
改訂日時: 2023-05-16