Search code examples
androidfragmentandroid-architecture-componentsandroidxandroid-viewmodel

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


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


Solution

  • 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)."