iOS でRxSwift を使ったユニットテストを書く
iOS でRxSwift を使っている場合、ユニットテストはexpectation を使って非同期部分をテストする方法があります。
以下は簡単なサンプルです。
import RxSwift import XCTest class MyRxTests3: XCTestCase { private let disposeBag = DisposeBag() func testSample1() { let expectation = self.expectation(description: "非同期") var singleValue = "" self.getSingle() .subscribe(onSuccess: { value in singleValue = value expectation.fulfill() }) .disposed(by: self.disposeBag) self.wait(for: [expectation], timeout: 1.0) XCTAssertEqual(singleValue, "Hoge") } private func getSingle() -> Single<String> { return Single.create { subscriber in subscriber(.success("Hoge")) return Disposables.create() } } }
これは冗長で、RxBlocking を使うと綺麗にかけます。
import RxBlocking import RxSwift import XCTest class MyRxTests3: XCTestCase { private let disposeBag = DisposeBag() func testSample2() { let singleValue = try! self.getSingle().toBlocking().single() XCTAssertEqual(singleValue, "Hoge") } private func getSingle() -> Single<String> { return Single.create { subscriber in subscriber(.success("Hoge")) return Disposables.create() } } }
.toBlocking でBlockingObservableに変換されます。 BlockingObservableはsuccess イベントが実行されるまで、メインスレッドをブロックし処理を待つので、 .subscribe で購読する必要がなくなります。
ちなみにCompletable の場合は toBlocking().materialize() です
let completable = Completable.create { subscriber in subscriber(.completed) return Disposables.create() } let result = completable .toBlocking() .materialize() switch result { case .completed: // ... default: // ... XCFailとか }