1. 概要

このチュートリアルでは、Jersey Test Frameworkを見て、それを使用して統合テストをすばやく作成する方法を確認します。

以前の記事ですでに見たように、JerseyはRESTfulWebサービスを開発するためのオープンソースフレームワークです。 JerseyとSpringを使用したAPIの作成の概要に関する記事–こちらでJerseyの詳細を学ぶことができます。

2. アプリケーションのセットアップ

Jersey Test Frameworkは、サーバー側コンポーネントの正しい実装を検証するのに役立つツールです。 後で説明するように、は、統合テストを作成するための高速で手間のかからない方法を提供し、HTTPAPIとの通信を非常にうまく処理できます。

同様に、ほとんどすぐに使用でき、Mavenベースのプロジェクトと簡単に統合できます。 フレームワークは主にJUnitに基づいていますが、TestNGでも使用できるため、ほとんどすべての環境で使用できます。

次のセクションでは、フレームワークを使用するためにアプリケーションに追加する必要のある依存関係を確認します。

2.1. Mavenの依存関係

まず、JerseyTestFrameworkのコア依存関係をpom.xmlに追加しましょう。

<dependency>
    <groupId>org.glassfish.jersey.test-framework</groupId>
    <artifactId>jersey-test-framework-core</artifactId>
    <version>2.27</version>
    <scope>test</scope>
</dependency>

いつものように、 MavenCentralから最新バージョンを入手できます。

ほぼすべてのJerseyテストは、事実上のGrizzlyテストコンテナファクトリを使用します。これも追加する必要があります。

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.27</version>
    <scope>test</scope>
</dependency>

ここでも、 MavenCentralで最新バージョンを見つけることができます。

3. 入門

この次のセクションでは、簡単なテストを作成するために必要な基本的な手順について説明します。

サーバーで単純なGreetingsリソースをテストすることから始めます。

@Path("/greetings")
public class Greetings {

    @GET
    @Path("/hi")
    public String getHiGreeting() {
        return "hi";
    }
}

3.1. テストの構成

次に、テストクラスを定義しましょう。

public class GreetingsResourceIntegrationTest extends JerseyTest {

    @Override
    protected Application configure() {
        return new ResourceConfig(Greetings.class);
    }
    //...
}

上記の例では、Jersey Test Frameworkを使用してテストを開発するには、JerseyTestをサブクラス化する必要があることがわかります。

次に、 configure メソッドをオーバーライドします。このメソッドは、テストのカスタムリソース構成を返し、Greetingsリソースのみを含みます。 もちろん、これは私たちがテストしたいリソースです。

3.2. 最初のテストを書く

グリーティングAPIからの簡単なGETリクエストをテストすることから始めましょう。

@Test
public void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() {
    Response response = target("/greetings/hi").request()
        .get();

    assertEquals("Http Response should be 200: ", Status.OK.getStatusCode(), response.getStatus());
    assertEquals("Http Content-Type should be: ", MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE));

    String content = response.readEntity(String.class);
    assertEquals("Content of ressponse is: ", "hi", content);
}

HTTP応答に完全にアクセスできることに注意してください。これにより、ステータスコードをチェックして操作が実際に成功したことを確認したり、応答の実際の本文を操作したりできます

上記の例で何をするかをより詳細に説明しましょう。

  1. HTTPGETリクエストを「/greetings/hi」に送信します
  2. HTTPステータスコードとコンテンツタイプの応答ヘッダーを確認してください
  3. 応答の内容に文字列「hi」が含まれていることをテストします

4. GETをテストしてリソースを取得する

これで、テストの作成に関連する基本的な手順を確認できました。 優れたJerseyMVCサポート記事で紹介したシンプルなFruitAPIをテストしてみましょう。

4.1. プレーンJSONを取得する

以下の例では、応答本文を標準のJSON文字列として使用しています。

@Test
public void givenFruitExists_whenSearching_thenResponseContainsFruit() {
    final String json = target("fruit/search/strawberry").request()
        .get(String.class);
    assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}"));
}

4.2. JSONの代わりにエンティティを取得する

応答をResourceエンティティクラスに直接マッピングすることもできます(例:

   @Test
    public void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() {
        final Fruit entity = target("fruit/search/strawberry").request()
            .get(Fruit.class);

        assertEquals("Fruit name: ", "strawberry", entity.getName());
        assertEquals("Fruit weight: ", Integer.valueOf(20), entity.getWeight());
    }

今回は、応答エンティティが変換されるJavaタイプを get メソッド( Fruit オブジェクト)で指定します。

5. POSTをテストしてリソースを作成する

APIで新しいリソースを作成するために、POSTリクエストをうまく利用します。 次のセクションでは、APIのこの部分をテストする方法を説明します。

5.1. プレーンJSONを投稿する

プレーンなJSON文字列を投稿して、新しいフルーツリソースの作成をテストすることから始めましょう。

@Test
public void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() {
    Response response = target("fruit/created").request()
        .post(Entity.json("{\"name\":\"strawberry\",\"weight\":20}"));

    assertEquals("Http Response should be 201 ", Status.CREATED.getStatusCode(), response.getStatus());
    assertThat(response.readEntity(String.class), containsString("Fruit saved : Fruit [name: strawberry colour: null]"));
}

上記の例では、Entityオブジェクトパラメータを受け取るpostメソッドを使用しています。 便利なjsonメソッドを使用して、対応するJSON文字列からエンティティを作成します。

5.2. JSONの代わりにエンティティを投稿する

getリクエストですでに見たように、Resourceエンティティクラスを直接投稿することもできます-例:

@Test
public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() {
    Fruit fruit = new Fruit("Blueberry", "purple");
    fruit.setWeight(1);

    Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
        .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));

    assertEquals("Http Response should be 400 ", 400, response.getStatus());
    assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater"));
}

今回は、 entity メソッドを使用して、Fruitエンティティを投稿し、メディアタイプをJSONとして指定します。

5.3. POSTを使用したフォーム送信

最後の投稿の例では、投稿リクエストを介してフォーム送信をテストする方法を確認します。

@Test
public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() {
    Form form = new Form();
    form.param("name", "apple");
    form.param("colour", null);
    
    Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED)
        .post(Entity.form(form));

    assertEquals("Http Response should be 400 ", 400, response.getStatus());
    assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null"));
 }

同様に、 Entity クラスを使用しますが、今回は、いくつかのパラメーターを含むフォームをpostリクエストに渡します。

6. 他のHTTP動詞のテスト

PUTやDELETEなどの他のHTTPエンドポイントをテストする必要がある場合があります。 これはもちろん、JerseyTestFrameworkを使用して完全に可能です。

簡単なPUTの例を見てみましょう。

@Test
public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() {
    Form form = new Form();
    form.param("serial", "2345-2345");

    Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED)
        .put(Entity.form(form));

    assertEquals("Http Response should be 400 ", 400, response.getStatus());
    assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid"));
}

request メソッドを呼び出すと、現在のリクエストオブジェクトで任意のHTTPメソッドを呼び出すことができます。

7. 追加機能

ジャージーテストフレームワークには、デバッグとテストに役立ついくつかの追加の構成プロパティが含まれています。

次の例では、指定された名前の機能をプログラムで有効にする方法を示します。

public class FruitResourceIntegrationTest extends JerseyTest {

    @Override
    protected Application configure() {
        enable(TestProperties.LOG_TRAFFIC);
        enable(TestProperties.DUMP_ENTITY);
        //...

テスト対象のJerseyアプリケーションを作成および構成するとき。 追加のプロパティを有効にすることもできます。 この場合、LOG_TRAFFICDUMP_ENTITY の2つのログプロパティを有効にします。これにより、テスト実行中に有用な追加のログ情報とデバッグ情報が提供されます。

8. サポートされているコンテナ

すでに述べたように、JerseyTestFrameworkでテストを作成するときに使用される事実上のコンテナーはGrizzlyです。 ただし、他の多くのコンテナがサポートされています:

  • インメモリコンテナ
  • OracleJDKのHttpServer
  • 単純なコンテナ(org.simpleframework.http
  • Jettyコンテナ(org.eclipse.jetty)

これらのコンテナの構成方法の詳細については、ドキュメントこちらを参照してください。

9. 結論

要約すると、このチュートリアルでは、JerseyTestFrameworkについて説明しました。 まず、Jersey Test Frameworkの構成方法を紹介し、次に非常に単純なAPIのテストを作成する方法を確認しました。

次のセクションでは、さまざまなGETおよびPOSTAPIエンドポイントのテストを作成する方法を説明しました。 最後に、JerseyTestFrameworkがサポートするいくつかの追加機能とコンテナーについて説明しました。

いつものように、記事の完全なソースコードは、GitHubから入手できます。