2024-10-24 014_學寫API_如何撰寫 API 的單元測試
2024-10-24 014_學寫API_如何撰寫 API 的單元測試
理解如何撰寫 API 的單元測試確實是一個需要逐步掌握的過程。下面我將詳細說明如何從基礎開始構思與撰寫單元測試,即使在不太理解的情況下,也可以一步步掌握整個過程。
1. 了解測試目的
首先,在撰寫單元測試之前,您必須理解為什麼要測試這個 API,這樣才能針對特定的目標撰寫測試。單元測試的目的是驗證您的代碼在不同的情況下是否都能正常運作,例如:
- 確保 API 方法可以被成功呼叫。
- 確保 API 返回的數據正確。
- 處理各種可能的輸入或狀況,確保代碼的穩定性。
2. 宣告與測試設計的基礎
在進行測試之前,您需要對系統的結構有一定的了解:
- 控制器:
PackageController
是我們要測試的控制器,它負責管理包裹的增刪改查操作。 - 模型:
Package
模型表示每個包裹的基本信息,例如追蹤號、寄件人、收件人等。
3. 宣告測試環境
在單元測試中,我們需要設置好測試的環境,以便模擬應用程序中的控制器。這包括創建控制器實例並模擬其所依賴的所有服務或物件。以下是如何一步步構思和宣告測試環境:
理解控制器的依賴項
- 在
PackageController
的建構函數中,您可能會發現它依賴於某些外部服務,例如日誌記錄器 (ILogger
)。 - 所以,在單元測試中,我們需要創建這些依賴項的實例,這樣才能創建
PackageController
的實例。
- 在
宣告成員變數
- **
_controller
**:這是我們要測試的控制器。 - **
_logger
**:這是控制器依賴的日誌記錄器。1
2private readonly PackageController _controller;
private readonly ILogger<PackageController> _logger;
- **
設置測試環境(建構函數)
- 測試類的建構函數
PackageControllerTests()
,用來初始化測試環境。通常,您需要通過依賴注入來創建控制器所需的外部資源。 - 例如使用
LoggerFactory
創建日誌記錄器,然後用這個日誌記錄器來創建控制器的實例:1
2
3
4
5public PackageControllerTests()
{
_logger = new LoggerFactory().CreateLogger<PackageController>();
_controller = new PackageController(_logger);
} - 為何這麼做:
- 測試過程中,我們需要一個
PackageController
實例來調用其中的方法,這是測試的核心。 - 控制器的建構函數可能需要某些服務(例如日誌記錄器),我們需要模擬這些服務來創建一個可測試的控制器實例。
- 測試過程中,我們需要一個
- 測試類的建構函數
4. 如何構思測試用例
構思測試用例的目標是確保各個 API 的功能運作正常。我們以 GetAllPackages()
方法為例,來說明如何構思測試。
理解方法的預期行為:
GetAllPackages()
:這個方法應該返回一個包含所有包裹的列表,並且返回的 HTTP 狀態碼應該是 200 OK。- 如果數據是空的,應返回空列表,而不是錯誤或其他不合適的狀態碼。
撰寫測試的步驟:
在測試中通常包含三個部分:準備 (Arrange)、執行 (Act) 和 **驗證 (Assert)**。
**準備 (Arrange)**:在這個階段,我們通常不需要額外的準備工作,因為我們的控制器已經在建構函數中初始化好了。
**執行 (Act)**:呼叫控制器的
GetAllPackages()
方法來取得結果。1
var okResult = _controller.GetAllPackages();
**驗證 (Assert)**:檢查返回的結果是否符合預期。這裡有兩個測試:
測試返回的結果是否為 200 OK:
1
Assert.IsType<OkObjectResult>(okResult.Result);
這一步是為了確保返回的 HTTP 狀態碼正確,這對於 API 的用戶來說非常重要。
測試返回的數據是否正確:
1
2
3var okResult = _controller.GetAllPackages().Result as OkObjectResult;
var items = Assert.IsType<List<Package>>(okResult.Value);
Assert.Empty(items); // 預期初始時包裹列表為空這裡的測試是確保返回的數據類型是
List<Package>
,並且在測試開始時這個列表應該是空的。
5. 如何構思單元測試即使不完全理解
如果您對測試不太理解,可以遵循以下步驟逐步進行:
參考現有的測試案例:
- 從其他已經存在的測試案例中學習如何構建測試,理解每個步驟的用途。
理解控制器的功能:
- 從控制器的代碼中了解每個方法的用途和行為,這樣您能更好地理解應該測試哪些場景。
測試基本場景:
- 最先測試的是基本場景,如:
- 方法是否能正常返回?
- 當列表是空的時候返回的數據是否符合預期?
- 當有數據時,是否能正確返回?
- 最先測試的是基本場景,如:
逐步測試不同的情況:
- 例如,您可以考慮:
- 如果用戶發送了無效的請求會怎麼樣?
- 如果資料庫中已經有數據,返回的列表是否正確?
- 如果新增重複的數據,系統應如何處理?
- 例如,您可以考慮:
小結
撰寫單元測試需要理解系統的結構和每個 API 的用途。在不完全理解的情況下,您可以:
- 參考已有代碼:觀察如何宣告和撰寫測試,理解每個步驟的目的。
- 從最簡單的場景開始測試:例如,檢查返回的狀態碼和基本的數據型別。
- 逐步學習代碼與框架:透過一次次的測試編寫,不斷熟悉框架及 API 的行為。
撰寫單元測試的過程是提高代碼質量、學習系統設計的一部分,即使一開始不完全理解,隨著您多次重複這個過程,理解會變得更加深入。希望這些建議能幫助您更好地構思和撰寫 API 的測試!