更新到 Fragment Testing 库 v1.1.0-alpha03 后崩溃

Crash after updating to Fragment Testing library v1.1.0-alpha03

更新到 androidx.fragment:fragment-testing v1.0-alpha03 后,我们现在在测试结束时遇到以下崩溃。

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Collection java.util.concurrent.ConcurrentHashMap.values()' on a null object reference
at androidx.lifecycle.ViewModel.clear(ViewModel.java:125)
at androidx.lifecycle.ViewModelStore.clear(ViewModelStore.java:62)

重要的是,这是我们模拟正在使用的 ViewModel 实例的测试,问题似乎与 lifecycle-viewmodel v2.1.0-alpha01 的相关更改有关,我们现在有一个传递依赖到。具体来说,崩溃发生在以下方法中,因为 mBagOfTags 为 null

final void clear() {
    mCleared = true;
    for (Object value: mBagOfTags.values()) {
        // see comment for the similar call in setTagIfAbsent
        closeWithRuntimeException(value);
    }
    onCleared();
}

解决了这个问题,现在的标题可能有点误导。自 2.1.0-alpha01 更新

以来,问题似乎通常与模拟 ViewModel 实例有关

因此,如前所述,问题归结为自至少 v2.1.0-alpha01 发布以来无法模拟 ViewModel 个实例。事实证明,解决方案是使用 spy() 代替。我正在使用 Koin,所以这意味着我的测试现在扩展了 KoinTest。然后我可以将以下内容添加到 test

val someViewModel: SomeViewModel by inject()

然后调用下面

    val spySomeViewModel = spy(someViewModel)
    loadKoinModules(module {
        viewModel(override = true) {
            spySomeViewModel
        }
    })

然后,就像使用 mock() 时的情况一样,可以做类似

的事情
doReturn(someResult).whenever(spySomeViewModel).someMethod()

更新: 来自 https://issuetracker.google.com/issues/122273087 "We've fixed this internally in https://android-review.googlesource.com/863029 to ensure that mocked ViewModels work as before and this will be available in the next version of ViewModel (and Fragment, etc. that relies on it)."