知識庫 / Testing RSS 訂閱

使用Java測試REST API

REST,Testing
HongKong
4
04:12 AM · Dec 06 ,2025

1. 概述

本教程將重點介紹通過集成測試,測試 REST API 的原理和機制。 具體來説,我們將使用實時請求和 JSON 負載對 API 進行測試,以確保其正確性和行為。

2. API 集成測試

API 集成測試涉及測試我們的應用程序與其外部依賴項(如數據庫、第三方服務或其它 API)之間的交互。 目標是確保系統不同組件協同工作,按預期運行。 與專注於單個組件的單元測試不同,集成測試通過向我們的 API 發送實際的 HTTP 請求並檢查響應,模擬真實世界的使用情況,從而確保一切都按預期工作。

2.1. API 集成測試的重要性

雖然單元測試確保單個代碼片段按照預期工作,但它們無法捕獲由於這些組件集成而產生的潛在問題。集成測試通過檢查系統不同部分之間的通信方式,從而解決這些問題,確保組件之間的誤解或錯誤不會影響整體功能。

此外,它們還能讓團隊對系統在生產環境中按預期運行充滿信心,從而降低部署後出現故障的風險。

2.2. 進行API集成測試的時間點

通常,API集成測試在單元測試之後,但在發佈之前進行。單元測試確認了單個組件的功能是否正常,集成測試則確保這些組件能夠協同工作,如預期。

集成測試也應在發佈前進行,以捕獲任何可能出現的迴歸問題或集成問題,這些問題可能與新功能或更新有關。

3. 測試狀態碼

為了確保API在用户不存在時按預期行為,我們可以測試響應狀態碼:

@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));
}

這是一個相當簡單的測試。它驗證了一條基本的成功路徑是否正常工作,而沒有為測試套件添加過多的複雜性。

如果,無論出於何原因,它失敗了,那麼我們不需要查看任何其他測試,直到我們修復它。

4. 測試媒體類型

我們還可以測試媒體類型,以確保響應的默認 Content-Type 是 JSON。

@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 數據。

如我們所見,我們遵循了一系列的邏輯測試流程。首先是響應的狀態碼(以確保請求已成功),然後是響應的媒體類型。只有在下一個測試中,我們才會查看實際的 JSON 負載。

5. 測試 JSON 負載

為了驗證 API 是否返回正確的數據,我們可以測試 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頭部請求特定類型的表示形式,服務器應尊重此請求。

6. 測試工具

我們將使用 Jackson 2 將原始 JSON 字符串反序列化為類型安全的 Java 實體:

public class GitHubUser {

    private String login;

    // standard getters and setters
}

我們僅使用一個簡單的實用工具來保持測試的整潔、可讀性和高層次的抽象程度:

public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> 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);
}

請注意,Jackson 忽略了 GitHub API 發送的未知屬性。這僅僅是因為 GitHub 上 User 資源的表示非常複雜,我們這裏不需要這些信息。

7. 依賴項

這些實用工具和測試依賴於以下庫,所有庫均可在 Maven Central 上找到:

8. 結論

這只是完整的集成測試套件的一部分。這些測試旨在確保 REST API 的基本正確性,而沒有深入到更復雜的場景。

例如,我們沒有涵蓋以下內容:API 的可發現性、相同資源的各種表示形式的消費等。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.