簡體   English   中英

如何測試RxSwift Observable.interval進度

[英]How to test RxSwift Observable.interval progress

我有一個視圖模型,其行為由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會打勾的虛擬時間?

是的,看看這個有你正在尋找的行為的簡單測試: https//github.com/ReactiveX/RxSwift/blob/b3f4bf1/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift#L496

要將TestScheduler交換為MainScheduler ,我建議您將其作為依賴項注入。

另外,要檢查_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的生命周期的需要。

你應該考慮暴露比_exerciseRemainingTime更少“內部”的_exerciseRemainingTime 也許類似於currentExercise: Observable<ExerciseEnum> ,它在內部基於_exerciseRemainingTime 這樣,您的視圖控制器可以訂閱並執行與視圖控制器相關的簡單工作,即可進行下一個練習。

另外,為了簡化測試,您可以將20變量注入到視圖模型中,這樣在測試中您可以提供更小的東西,如3 ,然后correct只需要幾個元素長。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM