RxJava Testing<二九>

在設計任何系統時,您須要保證操做的正確性,而且隨着系統在其整個生命週期內進行修改,此質量不會消退。您將設計測試,理想狀況下,測試應該是自動化的。現代軟件由完全的單元測試支持,Rx代碼應該沒有什麼不一樣。ios

在單元測試中,咱們通常會預約義一些序列值來驗證,可是對於異步代碼呢?好比下面的代碼git

Observable.interval(1, TimeUnit.SECONDS).take(5)github

這是一個須要5秒鐘才能完成的序列。這意味着使用此序列的每一個測試都須要5秒或更長時間。若是您要運行數千個測試,這根本不方便。併發

TestScheduler

上面的代碼不只耗費時間,並且在等待時實際上浪費了全部的時間。若是您能夠快進時鐘,那麼幾乎能夠當即評估該序列。您實際上沒法快進系統的時鐘,但您能夠快進虛擬時鐘。在Rx中,設計決定只經過調度程序使用時間。此決定容許您使用稱爲TestScheduler的虛擬化時間的調度程序替換。異步

TestScheduler的調度方式與咱們在[Scheduling and threading]一章中所見的調度程序相同(/Part 4 - Concurrency/1. Scheduling and threading.md))。它會安排當即或未來執行的操做。不一樣之處在於時間被凍結,只能根據要求進行。咱們決定時間進展和多少。單元測試

advanceTimeTo

顧名思義,advanceTimeTo將執行計劃到特定時刻的全部操做。這包括在調度程序被快進時調度的動做,即由其餘動做調度的動做。測試

輸出:spa

咱們安排了3個任務:一個是當即執行,另外兩個是未來執行。調度程序將按計劃的時間順序同步執行在該段時間內安排的全部任務。線程

advanceTimeTo容許您將時間設置爲任何值,包括當前時間以前的值。此實現決策可能會在測試中沒必要要地引入bug,所以在適用時最好使用下一個方法。設計

advanceTimeBy

advanceTimeBy提早相對於當前時刻的時間。在其餘方面,像advanceTimeTo同樣。

 

輸出:

triggerActions

triggerActions不提早時間。它只執行計劃到目前爲止執行的操做。

輸出:

Scheduling collisions

沒有什麼能阻止在同一時刻併發執行。當發生這種狀況時,咱們會發生scheduling衝突。執行兩個同時執行任務的順序與調度它們的順序相同。

輸出:

Testing

涉及異步操做的Rx operators使用scheduler調度這些操做。若是您查看Observable中的全部運算符,您將看到此類運算符具備scheduler的重載。這是您能夠爲TestScheduler補充實時調度程序的方法。

下面是一個示例,咱們將測試Observable.interval的輸出與咱們指望它發出的內容。

輸出:

這對於測試小的Rx代碼片斷(例如自定義運算符)很是有用。一個完整的系統可能會單獨使用schedulers,從而使咱們的虛擬時間失效。Lee Campbell建議使用咱們本身的提供商來抽象Rx的調度工廠(Schedulers)。在調試模式下,咱們的自定義調度程序工廠將使用TestScheduler替換全部調度程序,而後咱們將使用它來控制整個系統的時間。

TestSubscriber

在上面的測試中,咱們手動收集了發出的值,並將它們與咱們的預期進行了比較。這個過程在測試中很常見,Rx與TestSubscriber一塊兒打包,這將爲咱們作到這一點。其事件處理程序將收集收到的每一個通知,並使它們可供咱們檢查。使用TestSubscriber,咱們以前的測試成爲:

輸出:

TestSubscriber收集的不只僅是值,而是經過如下方法露出它們:

這裏有兩件事須要注意。首先是getLastSeenThread方法。TestSubscriber檢查什麼線程被喚起而且記錄最新的。例如,若是要驗證GUI線程上是否執行了操做,那麼這將很是有用。另外一個有趣的事情是,可能會有多個終止事件,這違背了咱們在本指南開頭時定義序列的方式。這也是subscriber可以收集多個終止事件的緣由。

TestSubscriber爲一些基本斷言:

還有一種方法能夠阻止執行,直到TestSubscriber訂閱的observable終止。

若是observable未能按時完成,則等待超時將拋出異常。

原文:https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%204%20-%20Concurrency/2.%20Testing%20Rx.md

相關文章
相關標籤/搜索