【问题标题】:Mock jetpack ViewModel for unit tests using Dagger2 (Robolectric)使用 Dagger2 (Robolectric) 进行单元测试的模拟 jetpack ViewModel
【发布时间】:2019-07-12 20:06:06
【问题描述】:

所以我正在尝试使用 Robolectric 为我的 Activity 编写一个单元测试,但是我不知道如何提供一个模拟视图模型来查看我的虚拟机是如何在类中直接实例化的。这是因为 jetpack 的生命周期感知 ViewModel 需要一个 Provider 类来实例化。因此,我实质上是在注入自定义提供程序,然后使用它来创建我的 ViewModel。我看过其他示例,但它们似乎都非常令人困惑。我如何做到这一点?

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]
    }
}

这就是我创建 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>)

【问题讨论】:

  • 你能告诉我们你的单元测试课吗?
  • 我遇到了类似的问题。这里的问题是活动知道它是如何被注入的。尝试查看 Dagger Android,它将允许您将字段依赖项注入到您的活动中。不过,这将需要大量的重构。
  • @SeanBlahovici 我目前在上面的示例中使用字段注入。还是您的意思是某种构造函数注入?

标签: android mvvm dagger-2 android-jetpack


【解决方案1】:

您应该从 appComponent 用于在此处创建依赖项的模块中注入一个测试视图模型。

不要自己创建视图模型。为 appComponent 创建 2 个模块,一个提供原始依赖项,另一个提供测试/模拟依赖项。像这样 -

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

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

在您的测试中,当您创建您的 AppComponent 时通过 TestAppModule 而不是 AppModule,那么您将获得模拟依赖项。

【讨论】:

  • 我的组件正在 Application 类 (MvvmDaggerApp) 中初始化。我不确定你是什么意思。我无法在我的测试类中创建它。
  • 对于单元测试,您需要在测试初始化​​代码中创建它。例如,在某些使用 @Setup 注释的方法中,在 Mockito 的情况下。
  • appComponent 仍在我的 Activity 的 onCreate 中被调用。我不明白我将如何为我的活动提供另一个组件。你能用代码示例解释一下吗?
  • 参加聚会有点晚了,但我在解决同样的问题时几乎失去了理智。您必须为测试目的创建另一个应用程序,这将扩展您的生产应用程序。在那里,您覆盖组件的创建以返回 TestComponent。锦上添花 - 在您的测试中,您在整个测试类上添加注释,例如 @Config(application = TestApplication::class) 希望它可以帮助某人:)
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 2015-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多