简体   繁体   English

使用Dagger2(Robolectric)进行单元测试的模拟jetpack ViewModel

[英]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. 所以我正在尝试使用Robolectric为我的Activity编写一个单元测试,但是我不知道如何提供一个模拟的视图模型,看看我的vm是如何直接在类中实例化的。 This is due to the fact that jetpack's lifecycle aware ViewModel requires a Provider class to instantiate. 这是因为jetpack的生命周期感知ViewModel需要Provider类进行实例化。 So, I'm essentially injecting the custom provider and then using that to create my ViewModel. 所以,我基本上是注入自定义提供程序,然后使用它来创建我的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: 这就是我创建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>)

You should inject a Test View Model from the module which appComponent is using to create dependencies here. 您应该从appComponent用于在此处创建依赖关系的模块注入测试视图模型。

Do not create the viewmodel yourself. 不要自己创建视图模型。 Create 2 modules for appComponent one which provides the original dependencies and other with test/mock dependencies. 为appComponent创建2个模块,提供原始依赖项,其他模块提供测试/模拟依赖项。 Something like this - 像这样的东西 -

@Module
public AppModule {
      public ViewModel appViewModel() { // return original here}
}

  @Module
public TestAppModule extends AppModule {
      public ViewModel appViewModel() { // return test/mock here}
}

In your test when you create Your AppComponent pass TestAppModule instead of AppModule, then you will get mocked dependencies. 在您的测试中,当您创建AppComponent传递TestAppModule而不是AppModule时,您将获得模拟的依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM