RxSwift文档六(单元测试)

单元测试

测试自定义操作符

RxSwift用RxTest为所有操作符测试,位于Rx.xcworkspace项目内的AllTests-*目标中。

这是典型的RxSwift操作符单元测试的示例:

func testMap_Range() {
    // 初始化测试调度程序。.
    // 测试调度程序实现虚拟时间与本地机器时钟分离。
    // 这样可以尽快运行模拟并证明所有事件都已处理完毕。
    let scheduler = TestScheduler(initialClock: 0)
    
    // 创建一个模拟热的可观察序列。
    // 序列将在指定的时间发出事件,无论是否有观察者订阅。
    // 这就是热的意思)。
    // 此可观察序列还将记录所有在其生命周期内的订阅(`subscriptions`属性)。
    let xs = scheduler.createHotObservable([
        .next(150, 1),  // first argument is virtual time, second argument is element value
        .next(210, 0),
        .next(220, 1),
        .next(230, 2),
        .next(240, 4),
        .completed(300) // virtual time when completed is sent
    ])
    
    // 默认情况下,``start`方法:
    // *运行模拟并记录所有事件
    //    使用`res`引用的观察者。
    // *在虚拟时间200订阅
    // *在虚拟时间1000处理订阅
    let res = scheduler.start { xs.map { $0 * 2 } }
    
    let correctMessages = Recorded.events(
        .next(210, 0 * 2),
        .next(220, 1 * 2),
        .next(230, 2 * 2),
        .next(240, 4 * 2),
        .completed(300)
    )
    
    let correctSubscriptions = [
        Subscription(200, 300)
    ]
    
    XCTAssertEqual(res.events, correctMessages)
    XCTAssertEqual(xs.subscriptions, correctSubscriptions)
}

对于非终止序列,不一定关心事件时间,也可以使用RxTest的XCTAssertRecordedElements来断言已发出的特定元素。终止事件(例如completed或error)将导致测试失败。

func testElementsEmitted() {
    let scheduler = TestScheduler(initialClock: 0)

    let xs = scheduler.createHotObservable([
        .next(210, "RxSwift"),
        .next(220, "is"),
        .next(230, "pretty"),
        .next(240, "awesome")
    ])

    let res = scheduler.start { xs.asObservable() }

    XCTAssertRecordedElements(res.events, ["RxSwift", "is", "pretty", "awesome"])
}

测试操作符组合(视图模型,组件)

如何测试组合操作符的示例包含在Rx.xcworkspace> RxExample-iOSTeststarget中。

定义RxTest扩展很容易,因此可以以可读的方式编写测试。内部提供的示例RxExample-iOSTests只是关于如何编写这些扩展的建议,但是如何编写这些测试有很多可能性。

// 预期事件和测试数据
    let (
        usernameEvents,
        passwordEvents,
        repeatedPasswordEvents,
        loginTapEvents,

        expectedValidatedUsernameEvents,
        expectedSignupEnabledEvents
    ) = (
        scheduler.parseEventsAndTimes("e---u1----u2-----u3-----------------", values: stringValues).first!,
        scheduler.parseEventsAndTimes("e----------------------p1-----------", values: stringValues).first!,
        scheduler.parseEventsAndTimes("e---------------------------p2---p1-", values: stringValues).first!,
        scheduler.parseEventsAndTimes("------------------------------------", values: events).first!,

        scheduler.parseEventsAndTimes("e---v--f--v--f---v--o----------------", values: validations).first!,
        scheduler.parseEventsAndTimes("f--------------------------------t---", values: booleans).first!
    )

集成测试

也可以使用RxBlocking运算符编写集成测试。

使用RxBlocking的toBlocking()方法,可以阻止当前线程并等待序列完成,允许同步访问它的结果。

测试序列结果的一种简单方法是使用toArray方法。一旦序列成功完成,它将返回所有元素的数组,或者throw如果错误导致序列终止。

let result = try fetchResource(location)
        .toBlocking()
        .toArray()

XCTAssertEqual(result, expectedResult)

另一种选择是使用materialize运算符,它可以更细致地检查序列。如果序列成功完成将返回MaterializedSequenceResult枚举包含.completed枚举和发出的元素,或者failed如果序列以错误终止包含发射的错误。

let result = try fetchResource(location)
        .toBlocking()
        .materialize()

// 用于在终止错误的情况下测试结果或错误
switch result {
        case .completed:
            XCTFail("Expected result to complete with error, but result was successful.")
        case .failed(let elements, let error):
            XCTAssertEqual(elements, expectedResult)
            XCTAssertErrorEqual(error, expectedError)
        }

// 用于在完成终止的情况下测试结果
switch result {
        case .completed(let elements):
            XCTAssertEqual(elements, expectedResult)
        case .failed(_, let error):
            XCTFail("Expected result to complete without error, but received \(error).")
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值