RxTest跟RxBlocking是基於RxSwift上,測試Rx-based的library,讓我們分兩天,大概的了解一下RxTest跟RxBlocking,個人覺得,RxBlocking的概念比較單純的,就從RxBlocking先講起吧!
RxBlocking概念是Observable stream轉換成BlockingObservable,是一種特殊的Observable,blocking就是阻斷的意思,他會阻斷當前的thread,就好像現在我們排隊要進餐廳,會有人把你擋下來幫你量體溫一樣,配合一些RxBlocking的operator,當符合條件時,就會返回結果,下面讓我們看個範例
在有限的序列當中,過濾出小於3的數字
let observable = Observable.of(1, 2, 3, 2, 5).filter { $0 < 3 }
// 1
let result = observable.toBlocking()
// 2
XCTAssertEqual(try result.first(), 1)
// 3
XCTAssertEqual(try result.last(), 2)
// 4
XCTAssertEqual(try result.toArray(), [1, 2, 2])
first()
是BlockingObservable的operator,可以攔截第一個元素,以範例來說就是數字1
last()
是BlockingObservable的operator,可以攔截最後一個元素,所以必須要等到Observable結束才會觸發,以範例來說就是數字2
toArray()
是BlockingObservable的operator,當Observable結束後,可以發送過的元素以陣列返回結果,以範例來說就是[1, 2, 2]
RxBlocking雖然好用,但仍然不夠靈活,於是一些情境下需要RxTest解決問題,RxTest提供TestScheduler,是一種特殊的Scheduler,它只能用於測試,並提供虛擬的時間、模擬的Observer跟模擬的Observable,下面讓我們看一個範例。
首先是測試的宣告、setUp()
和tearDown()
部分
// 1
var scheduler: TestScheduler!
override func setUp() {
super.setUp()
// 2
scheduler = TestScheduler(initialClock: 0)
}
override func tearDown() {
super.tearDown()
}
主要測試的程式
func testRxTestExample() {
let disposeBag = DisposeBag()
// 1
let observer = scheduler.createObserver(Int.self)
// 2, 3
let observable = scheduler.createColdObservable([
Recorded.next(100, 1),
Recorded.next(200, 2),
Recorded.next(300, 3),
Recorded.next(400, 2),
Recorded.next(500, 1)
])
let filterObservable = observable.filter { $0 < 3 }
filterObservable.subscribe(observer).disposed(by: disposeBag)
// 4
scheduler.start()
// 5
let results = observer.events.compactMap { $0.value.element }
XCTAssertEqual(results, [1, 2, 2, 1])
}
TestableObserver<Int>
.next
方法,會把Element轉成Event,這也是createColdObservable或createHotObservable所需要的inputevents
,它是[Recorded<Event<Element>>]
型態,也就是所有Observable所.next
發送的元素都存在這變數當中,再使用compactMap
把陣列降。Cold/Hot Observable可以視為Observable的一種屬性差異
Hot Observable表示不管有無訂閱,都會發送元素,也代表一建立後,就會佔用資源,任何訂閱者從中訂閱後,可接收所發出的元素,像是Button或是Subject。
Cold Observable僅在訂閱後,才會開始發送元素,也代表有人訂閱時才會佔用資源,訂閱者在訂閱時可以從第一個元素開始接收,就像是data stream或是跟server請求資料
根據RxSwift: Reactive Programming with Swift所提到,在Rx世界中,通常是在測試時,需要較大的控制權,才會需要去探討到Cold/Hot Observable,不然平常只要使用Rx所提供的Observable即可。
一轉眼就22天了,離30天也不遠了,越到後期越累呀,第一次覺得一個月這麼長...明天會嘗試將昨天的程式加上測試,明天見