Mil*_*mak 3 reactive-programming ios swift rx-swift
我有一个视图模型,其行为由一个人控制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()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想对此进行测试,以观察事件的发生时间和价值_exerciseRemainingTime.
有没有办法如何使用TestScheduler模拟虚拟时间_oneSecondTimer来勾选?
是的,看看这个有你正在寻找的行为的简单测试:https://github.com/ReactiveX/RxSwift/blob/b3f4bf1/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift#L496
要交换TestScheduler的MainScheduler,我建议你注入它作为一个依赖.
另外,要检查值_exerciseRemainingTime,您需要删除private.但是,我不建议测试你班级的内部.删除private是您的标志.相反,如果您要注入一个负责其工作的对象progressToNextExercise,那么您可以测试它是否接到了进行下一个练习的调用.您只需在测试期间传入该对象的测试版本,就像您TestScheduler对调度程序一样.这样就不需要_exerciseRemainingTime公开测试它,甚至不知道它.
但是,_exerciseRemainingTime为了这个问题的主要目的忽略了可见性,这就是我对调度程序的意思:
WorkoutViewModel.swiftclass 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
}
}
Run Code Online (Sandbox Code Playgroud)
WorkoutViewModelTest.swiftfunc 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)
}
Run Code Online (Sandbox Code Playgroud)
要考虑几个注意事项:
为了让测试调度程序订阅和处置,我subscribeNext从视图模型中删除了它.我认为这无论如何都会改进它,因为您应该使用视图控制器订阅并仅使用视图模型为您提供Observable.这消除了视图模型需要具有配置包并管理Disposables 的生命周期的需要.
你应该考虑暴露一些不那么"内在"的东西_exerciseRemainingTime.也许是类似的东西currentExercise: Observable<ExerciseEnum>,内在的基础_exerciseRemainingTime.这样,您的视图控制器可以订阅并执行与视图控制器相关的简单工作,即可进行下一个练习.
此外,为了简化测试,您可以将20变量注入到视图模型中,这样在测试中您可以提供更小的东西3,然后correct只需要几个元素.
| 归档时间: |
|
| 查看次数: |
1269 次 |
| 最近记录: |