Awaitility同步異步工具實戰示例詳解

引言

在編寫測試用例的時候遇到有異步或者隊列處理的時候經常會用到 Thread.sleep() 等待來進行測試。例如:DLedger 測試選舉的過程。當DLedger Leader下線。此時DLedger會重新發起選舉,這個選舉的過程是需要一定時間。很多時候在測試代碼中就會使用 Thread.sleep 。

由於選舉需要的時間多少不確定所以sleep時間就會設置為開發者經驗的最大值。這樣會造成測試代碼會變得很慢。 當然開發者可以通過自己輪詢來實現減少時間的消耗。

下面介紹一個處理這個一類問題的工具:awaitility

1. awaitility入門

Maven:

<dependency>
      <groupId>org.awaitility</groupId>
      <artifactId>awaitility</artifactId>
      <version>xxxx</version>
      <scope>test</scope>
</dependency>

文章編寫的時候版本為:4.2.0

1.1 靜態導入

為瞭有效地使用Awaitility,建議從Awaitility框架中靜態地導入以下方法:

org.awaitility.Awaitility.*

在使用的時候需要搭配Java的時間相關的類以及Junit相關類:

java.time.Duration.*

java.util.concurrent.TimeUnit.*

org.junit.Assert.*

1.2 簡單例子

例子1:

await().until(newUserIsAdded());

等待直到執行newUserIsAdded()返回true. 這個是沒有返回值的。

例子2:

await().atMost(5, SECONDS).until(newUserWasAdded());

最多等待5秒,等待直到執行newUserIsAdded()返回true. 這個是沒有返回值的。

例子3:

await().until( userRepositorySize(), equalTo(1) );

等待直到執行userRepositorySize()返回方法對應的值. 這個是有返回值

更多的例子可以參照官網 使用例子

2. awaitility在RocketMQ中的實戰

在RocketMQ的test cases 中有一些使用瞭 Thread.sleep,接下來我們看看如何使用awaitility進行優化,減少測試用例的執行時間。以ControllerManagerTest測試用例為例子來解決,在代碼中可以看到有這樣的代碼:

上圖框出來的代碼主要的作用是什麼呢?等待Broker的Master過期,但是過期的時間我們根據設置的心跳的過期時間來預估時間。所以這裡填寫的是6秒當然你也可以填寫10秒或者更長。

解決之前的執行時間:

使用awaitility對代碼進行改造重構:

重構後的代碼,如上圖的紅線框出來部分。當然我這裡還對其他的進行處理。

有興趣的可以關註一下RocketMQ的這個ISSUE:github.com/apache/rock…

使用awaitility重構後的執行時間:

時間有明顯的下降。相比之前的下降瞭5秒左右。

3. 總結

  • 在測試過程中引入awaitility能夠很大程度上方便測試,無需要每次都憑經驗去預估時間。並且很多時候這個Thread.sleep的時間不是很好估算。減少瞭單元測試執行的時間。特別是像RocketMQ這樣大型的項目單元測試很多。並且很多都是去測試分佈式的,如果使用Thread.sleep會導致整個單元測試的時間很長。
  • 無需自己去實現輪詢來減少單元測試的時間。

以上就是Awaitility同步異步工具實戰示例詳解的詳細內容,更多關於Awaitility同步異步工具實的資料請關註WalkonNet其它相關文章!

推薦閱讀: