如何使用 Mockito 延遲存根方法來回應
一、簡介
Mockito 允許開發人員存根方法以傳回特定值或執行某些操作。在某些測試場景中,我們可能需要在存根方法的回應中引入延遲來模擬現實條件,例如網路延遲或緩慢的資料庫查詢。
在本教程中,我們將探索使用 Mockito 引入此類延遲的不同方法。
2. 了解存根方法中延遲的必要性
在存根方法中引入延遲在多種情況下可能是有益的:
- 模擬現實條件:測試應用程式如何處理延遲和超時
- 效能測試:確保應用程式能夠優雅地處理緩慢的回應
- 調試:重現和診斷與定時和同步相關的問題
在測試中添加延遲可以幫助我們創建更強大、更有彈性的應用程序,為現實場景做好更好的準備。
3.Maven依賴
讓我們將mockito-core和awaitility的Maven 依賴項加入我們的專案:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.1</version>
<scope>test</scope>
</dependency>
4. 設定
讓我們建立一個PaymentService來模擬處理付款:
public class PaymentService {
public String processPayment() {
// simulate processing payment and return completion status
return "SUCCESS";
}
}
我們還將引入延遲來以各種方式模擬處理付款。
5.使用Thread.sleep()引入延遲
引入延遲的最簡單方法是在存根方法中使用Thread.sleep() 。此方法將目前執行緒的執行暫停指定的毫秒數:
@Test
public void whenProcessingPayment_thenDelayResponseUsingThreadSleep() {
when(paymentService.processPayment()).thenAnswer(invocation -> {
Thread.sleep(1000); // Delay of one second
return "SUCCESS";
});
long startTime = System.currentTimeMillis();
String result = paymentService.processPayment();
long endTime = System.currentTimeMillis();
assertEquals("SUCCESS", result);
assertTrue((endTime - startTime) >= 1000); // Verify the delay
}
在此範例中, PaymentService模擬的processPayment()方法將等待兩秒鐘,然後返回「SUCCESS」。此方法很簡單,但會阻塞線程,這可能不適合測試非同步操作或在生產環境中使用。
6. 使用 Mockito 的答案引入延遲
Mockito 的Answer介面提供了更靈活的存根方法。我們可以使用它來引入延遲以及其他自訂行為:
@Test
public void whenProcessingPayment_thenDelayResponseUsingAnswersWithDelay() throws Exception {
when(paymentService.processPayment()).thenAnswer(AdditionalAnswers.answersWithDelay(1000, invocation -> "SUCCESS"));
long startTime = System.currentTimeMillis();
String result = paymentService.processPayment();
long endTime = System.currentTimeMillis();
assertEquals("SUCCESS", result);
assertTrue((endTime - startTime) >= 1000); // Verify the delay
}
在此範例中,Mockito 的AdditionalAnswers類別中的answersWithDelay()方法用於在返回「SUCCESS」之前引入 2 秒的延遲。這種方法抽象化了延遲邏輯,使程式碼更乾淨且更易於維護。
7.使用等待引入Awaitility
Awaitility 是一種用於在測試中同步非同步操作的 DSL。它可用於等待滿足條件,但也可能導致延遲。這使得它對於測試非同步程式碼特別有用:
@Test
public void whenProcessingPayment_thenDelayResponseUsingAwaitility() {
when(paymentService.processPayment()).thenAnswer(invocation -> {
Awaitility.await().pollDelay(1, TimeUnit.SECONDS).until(()->true);
return "SUCCESS";
});
long startTime = System.currentTimeMillis();
String result = paymentService.processPayment();
long endTime = System.currentTimeMillis();
assertEquals("SUCCESS", result);
assertTrue((endTime - startTime) >= 1000); // Verify the delay
}
在此範例中, Awaitility.await().pollDelay(1, TimeUnit.SECONDS).until(() -> true)在傳回「SUCCESS」之前引入了至少一秒的延遲。 Awaitility 流暢的 API 使其易於閱讀和理解,並為等待非同步條件提供了強大的功能。
8. 確保測試穩定性
為了確保引入延遲時測試套件的穩定性,請考慮以下最佳實踐:
- 設定適當的逾時:確保逾時足夠大以適應延遲,但不會太長而影響測試執行時間。這可以防止出現問題時測試無限期掛起。
- 模擬外部依賴項:如果可能,模擬外部依賴項以可靠地控制和模擬延遲。
- 隔離延遲的測試:隔離有延遲的測試,以防止它們影響整個測試套件的執行時間。這可以透過將此類測試分組到單獨的類別或在不同的環境中運行它們來完成。
9. 結論
延遲 Mockito 中存根方法的反應對於模擬現實條件、測試效能和除錯非常有用。
在本文中,我們透過使用Thread.sleep() 、 Awaitility和 Mockito 的Answer有效地引入了這些延遲。此外,確保測試穩定性對於維持可靠、穩健的測試至關重要,並且結合這些技術可以幫助創建為現實場景準備的更具彈性的應用程式。
與往常一樣,程式碼可以在 GitHub 上取得。