android - PublishSubject 和 TestScheduler 出现问题,未发出项目

标签 android unit-testing testing rx-java rx-android

我一直面临主题和 TestScheduler 的问题。如果我使用 Trampoline 调度程序,我的测试会通过,但由于某种原因,如果我使用 TestScheduler,测试会失败。

这是我的示例测试和相关类(class)。

@RunWith(MockitoJUnitRunner::class)
class DemoViewModelTest  {


    //Error Mocks
    private val actionsStream: PublishSubject<DemoContract.ViewEvent> = PublishSubject.create()

    private lateinit var viewModel: DemoViewModel

    private val handler = mock(DemoContract.Handler::class.java)

    @Before
    fun setup() {
        viewModel = DemoViewModel(schedulersProvider, handler)
        viewModel.viewEventsStream = actionsStream
    }

    @Test
    fun testUpdateCounter() {
        actionsStream.onNext(DemoContract.ViewEvent.UpdateClick)
        testScheduler.triggerActions()
        verify(handler).onUpdate()

    }


    protected var testScheduler = TestScheduler()

    protected var schedulersProvider: SchedulersProvider = object : SchedulersProvider() {
        override fun mainThread(): Scheduler {
            return testScheduler
        }

        override fun io(): Scheduler {
            return testScheduler
        }

        override fun computation(): Scheduler {
            return testScheduler
        }

        override fun newThread(): Scheduler {
            return testScheduler
        }

        override fun trampoline(): Scheduler {
            return testScheduler
        }

        override fun single(): Scheduler {
            return testScheduler
        }
    }
}

还有我的 ViewModel 类

class DemoViewModel (val schedulersProvider: SchedulersProvider, val handler:DemoContract.Handler) : DemoContract.ViewModel() {

    var viewEventsStream: Observable<DemoContract.ViewEvent>? = null
        set(value) {
            field = value
            subscribeToViewEvents()
        }

    private fun subscribeToViewEvents() {
        viewEventsStream?.let {
            it.subscribeOn(schedulersProvider.io())
                .observeOn(schedulersProvider.mainThread())
                .subscribe(object:Observer<DemoContract.ViewEvent>{
                    override fun onComplete() {

                    }

                    override fun onSubscribe(d: Disposable) {
                    }

                    override fun onNext(t: DemoContract.ViewEvent) {
                        onViewEvent(t)
                    }

                    override fun onError(e: Throwable) {
                    }

                })

        }
    }
     fun onViewEvent(event: DemoContract.ViewEvent) {
        when (event) {
            is DemoContract.ViewEvent.UpdateClick -> {
               handler.onUpdate()
            }
        }
    }

}

我的契约(Contract)类别是

interface DemoContract {
        abstract class ViewModel

        sealed class ViewEvent {
            object UpdateClick : ViewEvent()
        }

        interface Handler{
            fun onUpdate()
        }
    }

关于这个的一些事情,如果我更换

viewModel.viewEventsStream = actionsStream

viewModel.viewEventsStream = Observable.just(DemoContract.ViewEvent.Update)

此测试通过。

有人可以解释一下吗,提前致谢。这是最小可运行的 project

最佳答案

非常感谢@akarnokd 为我指明了正确的方向。事实证明,这是添加的 PublishSubject 的订阅者(subscribeActual 调用)与我在测试中触发的 onNext 调用之间的竞争条件。 onNext 调用在前者发生之前返回。

解决方案是显式调用 triggerActions 两次,一次在订阅后立即调用,一次在发射后调用。

改变这个

    @Before
    fun setup() {
        viewModel = DemoViewModel(schedulersProvider, handler)
        viewModel.viewEventsStream = actionsStream
    }

    @Before
    fun setup() {
        viewModel = DemoViewModel(schedulersProvider, handler)
        viewModel.viewEventsStream = actionsStream
        testScheduler.triggerActions()
    }

关于android - PublishSubject 和 TestScheduler 出现问题,未发出项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53519339/

相关文章:

unit-testing - 什么是单元测试以及如何进行单元测试?

selenium - 按子文本选择节点

android - 当用户未更新状态时如何跳过 switch.setOnCheckedChangeListener

java - 调用 removeLocationUpdates 后位置回调不会停止

android - 如何提取 Lollipop 版状态栏中的通知文本?

Android:Theme.resolveAttribute 返回 0 原因 Resources$NotFoundException:资源 ID #0x0

c# - 使用 FxCop 获得百分比代码覆盖率

unit-testing - 如何在 Swift 中设置单元测试?

javascript - Protractor 中的 Jasmine 助手

algorithm - 在哪里可以找到图形测试套件?