我正在使用MockK测试MyFragment
。该片段在Observer
方法中为公共的可变LiveData
注册了onViewCreated
。 Observer
在模拟的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
观察者在值更改时立即触发,而不是在下一个循环/循环事件中触发。
修改
实际上不应该是:
listener
)注入片段listener
listener
值更改viewmodel.instruct(ReadWriteObj)
verify
确认viewmodel.instruct
被ReadWriteObj
呼叫编辑2
我知道我可以在单元测试中插入Thread.sleep(1000)
来解决此问题,但这确实是一种时髦的代码味道。目前,验证和观察者行为之间存在大约500毫秒的时间,这是从2013年开始在笔记本电脑上使用的。理论上,如果在某些较慢的机器上运行此单元测试,则睡眠根本无法解决问题。>