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の処理などの詳細は、インラインではなく、ユーティリティメソッドを使用して行う必要があります。
参考文献:
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セントラルで利用可能な以下のライブラリを使用します。
-
Hamcrest(オプション)
7. 結論
これは、完全な統合テストスイートがすべきことの一部にすぎません。 テストは、より複雑なシナリオに入ることなく、ensuring basic correctness for the REST APIに焦点を合わせます。
たとえば、以下は対象外です:APIの検出可能性、同じリソースの異なる表現の消費など。
[.iframe-fluid] ##
これらすべての例とコードスニペットの実装はover on Githubにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。