如何测试 RxSwift Observable.interval 进度

标签: rx-swift ios Swift
发布时间: 2017/3/6 23:34:06
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我有一个视图模型谁有行为控制的 Observable.interval 。从本质上说,它更新计时器的标签上每个 next 和后一段时间,更新另一个值。

修剪的示例︰

class WorkoutViewModel {
    private var _oneSecondTimer: Observable<Int> {
        return Observable<Int>.interval(1, scheduler: MainScheduler.instance)
    }
    private let _exerciseRemainingTime: Variable<Int> = Variable(20)

    func setupBehaviour() {
        _oneSecondTimer.subscribeNext() { [unowned self] _ in
            self._exerciseRemainingTime.value -= 1
            if self._exerciseRemainingTime.value == 0 {
                self.progressToNextExercise()
            }
        }
    }
}

要测试此,观察事件的时间和价值的 _exerciseRemainingTime

还有如何使用 TestScheduler 来模拟虚拟的时间 _oneSecondTimer 会滴答?

解决方法 1:

是的看看这个简单的测试,你正在寻找的行为︰ https://github.com/ReactiveX/RxSwift/blob/b3f4bf1/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift#L496

可供换用 TestSchedulerMainScheduler ,我会建议你把它注射作为依赖关系。

同时,要检查的值 _exerciseRemainingTime ,您将需要删除 private 。 我不会建议但是测试您的类的内部。删除 private 是你的标志。 相反,如果你被注入对象谁的责任是要做 progressToNextExercise ,然后你可以测试它接到电话到下一个练习的进展。 在测试期间,就象你只会通过在该对象的测试版本 TestScheduler 调度程序。 这将删除需要使 _exerciseRemainingTime 公共测试它,或即使知道此事。

然而,忽略的可见性 _exerciseRemainingTime 为了这个问题的主要目的,在这里是我的意思是关于调度程序︰

WorkoutViewModel.swift

class WorkoutViewModel {
    private var _oneSecondTimer: Observable<Int> {
        return Observable<Int>.interval(1, scheduler: scheduler)
    }

    // not `private` anymore.  also, a computed property
    var _exerciseRemainingTime: Observable<Int> {
        return self._oneSecondTimer.map { i in
            20 - i
        }
    }

    // injected via `init`
    private let scheduler: SchedulerType

    init(scheduler: SchedulerType) {
        self.scheduler = scheduler
    }
}

WorkoutViewModelTest.swift

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

    let res = scheduler.start(0, subscribed: 0, disposed: 23) {
        WorkoutViewModel(scheduler: scheduler)._exerciseRemainingTime
    }

    let correct = [
        next(1, 20), // output .Next(20) at 1 second mark
        next(2, 19), // output .Next(19) at 2 second mark
        next(3, 18),
        next(4, 17),
        next(5, 16),
        next(6, 15),
        next(7, 14),
        next(8, 13),
        next(9, 12),
        next(10, 11),
        next(11, 10),
        next(12, 9),
        next(13, 8),
        next(14, 7),
        next(15, 6),
        next(16, 5),
        next(17, 4),
        next(18, 3),
        next(19, 2),
        next(20, 1),
        next(21, 0),
        next(22, -1),
    ]

    XCTAssertEqual(res.events, correct)
}

一对夫妇的笔记来考虑︰

为了让测试调度器订阅和处置,删除 subscribeNext 从视图模型。 我认为这将提高它不管怎么说,你应该订阅与视图控制器和只使用视图模型为您提供 Observable 。 这省却了视图模型要处置袋和管理的生命周期为 Disposable s。

你真的应该考虑揭露了一些更少的"内部",比 _exerciseRemainingTime 。 有些事或许喜欢 currentExercise: Observable<ExerciseEnum> ,这国内基于 _exerciseRemainingTime 。 这样一来,您的视图控制器可以订阅,并做简单的视图控制器相关工作的控制到下一个练习。

此外,为了简化测试,你可以注入 20 变量视图模型,在测试中,您可以提供一些小像 3 ,然后 correct 将只需要几个元素长。

赞助商