Android 如何让视图模型实现测试服务,而Dagger2安装程序扩展了DaggerApplication,并使用Component.Builder
在测试期间,我的视图模型仍在使用生产服务,我希望它们使用测试服务。我正在使用robolectric进行测试,但仍然没有找到解决问题的方法 我认为最有希望的是在我的测试片段中使用viewModelFactory生成器,比如Android 如何让视图模型实现测试服务,而Dagger2安装程序扩展了DaggerApplication,并使用Component.Builder,android,kotlin,dagger-2,robolectric,Android,Kotlin,Dagger 2,Robolectric,在测试期间,我的视图模型仍在使用生产服务,我希望它们使用测试服务。我正在使用robolectric进行测试,但仍然没有找到解决问题的方法 我认为最有希望的是在我的测试片段中使用viewModelFactory生成器,比如ViewModelUtil.createFor(mockedViewModel)在测试片段中使用。但这对我不起作用,在运行startFragment时,在模拟viewModel中创建的测试服务将被生产服务替换,如下所示 我的主应用程序扩展了DaggerApplication(),
ViewModelUtil.createFor(mockedViewModel)
在测试片段中使用。但这对我不起作用,在运行startFragment
时,在模拟viewModel中创建的测试服务将被生产服务替换,如下所示
我的主应用程序扩展了DaggerApplication(),而我的生产组件使用了@component.Builder,因此我无法在构建过程中指定模块
此外,我还尝试从我的AppComponent
扩展TestAppComponent
,但这似乎也不管用
我还尝试在MyApplication.kt中将生成器设置为静态对象,如下所示:
companion object {
var builder: AndroidInjector.Factory<MyApplication> =
DaggerAppComponent.builder()
}
...
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return builder.create(this)
}
但这不起作用,因为a类型不匹配。如果有某种解决方案,从DaggerApplication()扩展仍然是一种可能性,我会对此非常感兴趣
以下是我的设置:
AppComponent.kt
@Singleton
@Component(modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityModule::class,
FragmentModule::class,
ProductionModule::class])
interface AppComponent : AndroidInjector<MyApplication>{
@Component.Builder
abstract class Builder : AndroidInjector.Builder<MyApplication>()
}
@Singleton
@Component(modules =[
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
TestModule::class])
interface TestAppComponent: AndroidInjector<MyApplication>{
@Component.Builder
abstract class Builder: AndroidInjector.Builder<MyApplication>()
}
ViewModelModule.kt
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factor: ViewModelFactory): ViewModelProvider.Factory
/*** Fragments ***/
@Binds
@IntoMap
@ViewModelKey(BagFragment.BagViewModel::class)
abstract fun bindBagViewModel(viewModel: BagFragment.BagViewModel): ViewModel
MyApplication.kt
class MyApplication: DaggerApplication(), HasActivityInjector, HasSupportFragmentInjector {
@Inject
lateinit var sharedPreferencesService: SharedPreferencesService
@Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>
@Inject
lateinit var supportFragmentInjector: DispatchingAndroidInjector<Fragment>
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
MultiDex.install(this)
}
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().create(this)
}
override fun activityInjector() = activityInjector
override fun supportFragmentInjector() = supportFragmentInjector
}
我当前的测试片段init方法如下所示:
private fun init() {
bagFragment = BagFragment.newInstance()
SupportFragmentTestUtil.startFragment(bagFragment, AppCompatActivity::class.java)
}
最后但并非最不重要的一个示例生产片段:
BagFragment.kt
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
lateinit var viewModel: BagViewModel
override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(BagViewModel::class.java)
}
当我调用SupportFragmentTestUtil.startFragment()
时,我假设AndroidInjection.inject(此)
将用生产模块替换我的伪测试模块。我还尝试将AndroidInjection.injection(this)
放在init
方法中,与onCreate
相反,但这会在其他地方给我带来问题,并且与文档相反。请帮忙
@Module
internal class TestModule {
@Provides
fun bagViewModel(dataService: FakeDataService,
authenticationService: FakeAuthenticationService,
favoritesService: FakeFavoritesService,
cartService: FakeCartService): BagFragment.BagViewModel {
return BagFragment.BagViewModel(dataService, authenticationService, favoritesService, cartService)
}
@Provides
@Singleton
fun dataService(): FakeDataService = FakeDataService()
@Provides
@Singleton
fun authenticationService(): FakeAuthenticationService = FakeAuthenticationService()
// provides many other things
private fun init() {
bagFragment = BagFragment.newInstance()
SupportFragmentTestUtil.startFragment(bagFragment, AppCompatActivity::class.java)
}
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
lateinit var viewModel: BagViewModel
override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(BagViewModel::class.java)
}