JavaでREST APIをテストする

JavaでREST APIをテストする

1. 概要

このチュートリアルでは、testing a REST API with live Integration Tests(JSONペイロードを使用)の基本的な原則と仕組みに焦点を当てています。

##主な目標は、APIの基本的な正確さをテストするための概要を提供することです。ここでは、例として最新バージョンのGitHub REST APIを使用します。

内部アプリケーションの場合、この種のテストは通常​​、継続的インテグレーションプロセスの後半のステップとして実行され、REST APIが既にデプロイされた後に消費されます。

RESTリソースをテストする場合、通常、テストが焦点を当てるべきいくつかの直交する責任があります。

  • HTTPresponse code

  • 応答内の他のHTTPheaders

  • payload(JSON、XML)

Each test should only focus on a single responsibility and include a single assertion.明確な分離に焦点を当てることには常に利点がありますが、この種のブラックボックステストを行う場合は、最初から複雑なテストシナリオを作成する傾向があるため、さらに重要です。

統合テストのもう1つの重要な側面は、Single Level of Abstraction Principleの順守です。テスト内のロジックは、高レベルで作成する必要があります。 リクエストの作成、サーバーへのHTTPリクエストの送信、IOの処理などの詳細は、インラインではなく、ユーティリティメソッドを使用して行う必要があります。

参考文献:

Springでの統合テスト

Spring Webアプリケーションの統合テストを作成するためのクイックガイド。

Spring Bootでのテスト

ユニットテストを効率的に記述するために、Spring Bootがテストをサポートする方法について学びます。

REST保証ガイド

REST保証の基本-REST APIのテストと検証を簡素化するライブラリーを調べてください。

2. ステータスコードのテスト

@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {

    // Given
    String name = RandomStringUtils.randomAlphabetic( 8 );
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );

    // When
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );

    // Then
    assertThat(
      httpResponse.getStatusLine().getStatusCode(),
      equalTo(HttpStatus.SC_NOT_FOUND));
}

これはかなり単純なテストです–it verifies that a basic happy path is working、テストスイートにあまり複雑さを追加しません。

何らかの理由で失敗した場合、これが修正されるまで、このURLの他のテストを調べる必要はありません。

3. メディアタイプのテスト

@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {

   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );

   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );

   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}

これにより、応答に実際にJSONデータが含まれるようになります。

お気づきかもしれませんが、we’re following a logical progression of tests –最初に応答ステータスコード(要求がOKであることを確認するため)、次に応答のメディアタイプ、そして次のテストでのみ実際のJSONペイロードを確認します。

4. JSONペイロードのテスト

@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {

    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );

    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );

    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

この場合、GitHubリソースのデフォルトの表現はJSONであることがわかっていますが、通常、応答の `++`Content-Typeヘッダーは、リクエストのAcceptヘッダーと一緒にテストする必要があります-クライアントは尋ねますサーバーが尊重する必要があるAcceptを介した特定のタイプの表現の場合。

5. テスト用ユーティリティ

Jackson 2を使用して、生のJSON文字列を型保証されたJavaエンティティに非整列化します。

public class GitHubUser {

    private String login;

    // standard getters and setters
}

テストをクリーンで読みやすく、抽象度を高く保つために、単純なユーティリティのみを使用しています。

public static  T retrieveResourceFromResponse(HttpResponse response, Class clazz)
  throws IOException {

    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}

GitHub APIが送信しているJackson is ignoring unknown propertiesに注意してください。これは、GitHubでのユーザーリソースの表現が非常に複雑になるためです。ここでは、その情報は必要ありません。

6. 依存関係

ユーティリティとテストは、Mavenセントラルで利用可能な以下のライブラリを使用します。

7. 結論

これは、完全な統合テストスイートがすべきことの一部にすぎません。 テストは、より複雑なシナリオに入ることなく、ensuring basic correctness for the REST APIに焦点を合わせます。

たとえば、以下は対象外です:APIの検出可能性、同じリソースの異なる表現の消費など。

[.iframe-fluid] ##

これらすべての例とコードスニペットの実装はover on Githubにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。