Sunday, 1 September 2019

Mock jetpack ViewModel for unit tests using Dagger2 (Robolectric)

So I'm trying to write a unit test for my Activity using Robolectric, however I have no idea how to provide a mocked viewmodel seeing as how my vm is instantiated directly in the class. This is due to the fact that jetpack's lifecycle aware ViewModel requires a Provider class to instantiate. So, I'm essentially injecting the custom provider and then using that to create my ViewModel. I've looked at other examples but they all seem extremely confusing. How do I achieve this?

class ActivityEpisodeList : AppCompatActivity() {

        @Inject
        lateinit var vmFactory: ViewModelProvider.Factory

        private lateinit var vm: ActivityViewModel


        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_episode_list)

            MvvmDaggerApp.get(this).appComponent.inject(this)

            vm = ViewModelProviders.of(this, vmFactory)[ActivityViewModel::class.java]
    }
}

This is how I'm creating my ViewModel:

@Module
abstract class ViewModelModule {

    @Binds
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(ActivityViewModel::class)
    internal abstract fun postListViewModel(viewModel: ActivityViewModel): ViewModel

}


@Singleton
class ViewModelFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)



from Mock jetpack ViewModel for unit tests using Dagger2 (Robolectric)

No comments:

Post a Comment