After updating to androidx.fragment:fragment-testing
v1.0-alpha03 we're now getting following crash at end of test.
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)
Importantly this is test where we're mocking instance of ViewModel
being used and issues seems to be related to associated changes to lifecycle-viewmodel
v2.1.0-alpha01 which we now have a transitive dependency to. Specifically crash is occurring in following method because mBagOfTags
is null
final void clear() {
mCleared = true;
for (Object value: mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);
}
onCleared();
}
Having worked through the issue, the title now is perhaps a little misleading. The issue seems to be generally with mocking ViewModel
instances since 2.1.0-alpha01 update
So the issue boiled down, as mentioned, to not being able to mock ViewModel
instances since at least v2.1.0-alpha01
release. The solution it turned out was to use spy()
instead. I'm using Koin
so what that meant was that my test extends KoinTest
now. I can then add following to test
val someViewModel: SomeViewModel by inject()
and then call following
val spySomeViewModel = spy(someViewModel)
loadKoinModules(module {
viewModel(override = true) {
spySomeViewModel
}
})
and then, as was case when using mock()
can do something like
doReturn(someResult).whenever(spySomeViewModel).someMethod()
UPDATE: from 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)."