Nimble RxTests
这个小巧的辅助库有助于连接 Swift 中最受欢迎的测试库之一(Quick)和响应式世界。第一次当我不得不为响应式项目编写测试时,我一直在使用 RxBlocking 或解包事件,通常使用 .debug() 来帮助理解在响应式链中发生了什么。过了一会儿,我想“噢,好吧!我有这个可爱的小 Nimble,我知道 XCAssert 辅助工具是为 RxTest 创建的,为什么不也在 Nimble 中做同样的呢?”在我意识到之前,我使用相同的代码帮助我在 3 或 4 个项目中将 Nimble 和 Rx 绑定在一起,并在其中每一个项目中复制相同的文件。
于是 NimbleRxTest 库应运而生。
用例
如果您正在使用 Nimble 并且 和 QuickNimble,那么您可能遇到过类似这样的问题
// Swift
import Quick
import Nimble
import RxSwift
import RxTest
protocol Alive {}
struct Fish: Alive {}
struct Shark: Alive {}
struct Boat {}
final class Dolphin {
var soundEmissions: Observable<String> {
return encounter.flatMapLatest { thing -> Observable<String> in
switch thing {
case is Fish:
return .just("click")
case is Alive:
return .just("whistle")
default:
return .empty()
}
}
}
var encounter = PublishSubject<Any>()
}
final class FactionSelectionViewModelTests: QuickSpec {
override func spec() {
describe("a reactive 🐬") {
var dolphin: Dolphin!
var testScheduler: TestScheduler!
var disposeBag: DisposeBag!
beforeEach {
dolphin = Dolphin()
testScheduler = TestScheduler(initialClock: 0)
disposeBag = DisposeBag()
}
describe("encountering") {
var encounters: [Recorded<Event<Any>>]!
context("with a series of things") {
beforeEach {
encounters = [
.next(100, Boat()),
.next(200, Fish()),
.next(300, Fish()),
.next(400, Shark()),
.next(500, Boat()),
.completed(600)
]
}
it("emits sounds accordingly") {
let observer = testScheduler.createObserver(String.self)
testScheduler
.createHotObservable(encounters)
.bind(to: dolphin.encounter)
.disposed(by: disposeBag)
dolphin
.soundEmissions
.bind(to: observer)
.disposed(by: disposeBag)
// Yeah let's just expect these sounds
let expected = ["click", "click", "whistle"]
testScheduler.start()
// Uhh, let's just assume checking the returned strings is enough.
// Also just hide those pesky nils. (If you are vigilant enough you
// see that the below compact map is intended to filter out one extra
// nil emission from the .completed event.)
expect(observer.events.compactMap { $0.value.element }).to(equal(expected))
}
}
}
}
}
}
相反,如果我们为 Nimble 编写合适的匹配器,我们可以这样写
// Same as above
it("emits sounds accordingly") {
let observer = testScheduler.createObserver(String.self)
testScheduler
.createHotObservable(encounters)
.bind(to: dolphin.encounter)
.disposed(by: disposeBag)
dolphin
.soundEmissions
.bind(to: observer)
.disposed(by: disposeBag)
let expected: [Recorded<Event<String>>] = [
.next(200, "click"),
.next(300, "click"),
.next(400, "whistle"),
.completed(600)
]
testScheduler.start()
expect(observer.events).to(equal(expected))
}
// Same as above
这不是很美吗?它解决了忽略事件和时间的问题,并且使我们免于映射苦难,结果产生更干净、更复杂的测试。
要求
- XCode 10.0
- Swift 4.2
安装
CocoaPods
使用pod --version
测试: 1.6.1
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'NimbleRxTest', '~> 1.0.0'
end
替换YOUR_TARGET_NAME
,然后在Podfile
目录中,输入
$ pod install