如何等待被测系统的内部观察者执行其lambda

时间:2019-12-07 21:57:59

标签: android kotlin android-livedata mockk

我正在使用MockK测试MyFragment。该片段在Observer方法中为公共的可变LiveData注册了onViewCreatedObserver在模拟的ViewModel中调用一个方法。但是,(基于读取日志输出,在单元测试中,verify似乎在Observer开始其lambda之前运行。

我的单元测试:

class Tests {
    @get:Rule val rule: TestRule = InstantTaskExecutorRule()
    //...
    @Test
    fun updates_vm_with_editingListener() {
        /* Given */
        val listener = MutableLiveData(false)
        fragment.editingListener = listener
        mActivity.setFragment(fragment) // <-- this attaches the fragment to a dummy activity

        /* When */
        listener.value = true

        /* Then */
        Log.d("MyFragmentTest", "running verify")
        verify { vm.instruct(ReadWriteObj) } // vm is a mockk'ed class
    }
}

MyFragment包含以下代码:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        editingListener.observe(this, Observer {
            Log.d(TAG, "editing changed to $it")
            when(it) {
                true -> mViewModel.instruct(ReadWriteObj)
                false -> mViewModel.instruct(ReadOnlyObj)
            }
            Log.d(TAG, "editing messaged mViewModel")
        })
    }

相关的日志输出为:

I/TestRunner: started: updates_vm_with_editingListener(FragmentTest)
D/FragmentTest: running verify
D/MyFragment: editing changed to true
D/MyFragment: editing messaged mViewModel
E/TestRunner: failed: updates_vm_with_editingListener(FragmentTest)
E/TestRunner: java.lang.AssertionError: Verification failed: call 1 of 1: MyViewModel(vm#1).instruct(eq(ReadWriteObj@2da49cd))). Only one matching call to LiftGroupCardViewModel(vm#1)/instruct(LiftGroupCardIntent) happened, but arguments are not matching:

匹配的具有不同参数的obj是在片段的init块中进行的调用,此处未进行测试。

我不明白。我的课程中的InstantTaskExecutorRule应该使LiveData观察者在值更改时立即触发,而不是在下一个循环/循环事件中触发。

修改

实际上不应该是:

  1. 创建模拟视图模型并将其注入片段
  2. 虚拟livedata(listener)注入片段
  3. 测试开始
  4. 与活动相关的片段
  5. 片段开始观察listener
  6. listener值更改
  7. 片段的观察者开枪,呼叫viewmodel.instruct(ReadWriteObj)
  8. verify确认viewmodel.instructReadWriteObj呼叫

编辑2

我知道我可以在单元测试中插入Thread.sleep(1000)来解决此问题,但这确实是一种时髦的代码味道。目前,验证和观察者行为之间存在大约500毫秒的时间,这是从2013年开始在笔记本电脑上使用的。理论上,如果在某些较慢的机器上运行此单元测试,则睡眠根本无法解决问题。

0 个答案:

没有答案