【问题标题】:Unit test for RxJava subject in ViewModelViewModel 中 RxJava 主题的单元测试
【发布时间】:2021-04-20 06:02:37
【问题描述】:

例如,我创建了一个需要测试的示例代码

class MyViewModel() : BaseViewModel() {

    private val valueSubject = BehaviorSubject.create<String>()

    private val viewState = MutableLiveData<State>()
    fun getViewState(): LiveData<State> = viewState

    init {
        disposables.add(valueSubject
                .debounce(150L, TimeUnit.MILLISECONDS) //problem
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    viewState.value = State(it)
                })
    }

    fun valueChanged(value: String) {
        viewState.value = State(value + " processing")
        valueSubject.onNext(value)
    }
}

例如,您需要编写一个文本,使用valueChanged ("12"),将捕获2 个viewState 更改,第一个更改是viewState.value = State (value + "processing"),第二个更改已经在valueSubject 订阅中。

我在debounce(150L, TimeUnit.MILLISECONDS) 中理解的问题,有这样的解决方案examples,但是有没有可能不扔掉壳?

测试的基本部分

@RunWith(MockitoJUnitRunner::class)
class Test {

    @get:Rule
    var rule: TestRule = InstantTaskExecutorRule()

    @Before
    fun setUp() {
        RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.onComputationScheduler(Schedulers.trampoline())
        RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
    }
}

【问题讨论】:

    标签: android unit-testing junit rx-java2


    【解决方案1】:

    正如您自己已经发现的那样,在处理各种“延迟”运算符(例如延迟、间隔、计时器和反跳)时,将调度程序的时钟向前移动是要走的路。

    为了帮助您完成设置过程,您可以使用自定义规则类并直接触发调度程序的事件。

    class RxTestSchedulerRule : Rule {
    
        lateinit var testScheduler: TestScheduler
    
        override fun onBefore() {
            testScheduler = TestScheduler()
            RxJavaPlugins.setIoSchedulerHandler { testScheduler }
            RxJavaPlugins.setComputationSchedulerHandler { testScheduler }
            RxJavaPlugins.setNewThreadSchedulerHandler { testScheduler }
            RxJavaPlugins.setSingleSchedulerHandler { testScheduler }
            RxAndroidPlugins.setMainThreadSchedulerHandler { testScheduler }
            RxAndroidPlugins.setInitMainThreadSchedulerHandler { testScheduler }
        }
    
        override fun onAfter() {
            RxJavaPlugins.reset()
            RxAndroidPlugins.reset()
        }
    }
    
    fun CompositeRules.testScheduler() = getRule<RxTestSchedulerRule>().testScheduler
    fun CompositeRules.advanceTimeBy(duration: Long, unit: TimeUnit) = getRule<RxTestSchedulerRule>().testScheduler.advanceTimeBy(duration, unit)
    fun CompositeRules.advanceTimeTo(duration: Long, unit: TimeUnit) = getRule<RxTestSchedulerRule>().testScheduler.advanceTimeTo(duration, unit)
    fun CompositeRules.triggerActions() = getRule<RxTestSchedulerRule>().testScheduler.triggerActions()
    

    那么在你的测试类中可以用这个来简化

    @RunWith(MockitoJUnitRunner::class)
    class Test {
    
        @get:Rule
        var rule: TestRule = RxTestSchedulerRule()
    
        @Test
        fun `test view state correctly handled`() {
           // Setup your stream
    
           advanceTimeBy(150L, TimeUnit.MILLISECONDS)
    
           // Assert obs has emitted view state
        }
    
    }
    ```
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多