Android 如何让视图模型实现测试服务,而Dagger2安装程序扩展了DaggerApplication,并使用Component.Builder

Android 如何让视图模型实现测试服务,而Dagger2安装程序扩展了DaggerApplication,并使用Component.Builder,android,kotlin,dagger-2,robolectric,Android,Kotlin,Dagger 2,Robolectric,在测试期间,我的视图模型仍在使用生产服务,我希望它们使用测试服务。我正在使用robolectric进行测试,但仍然没有找到解决问题的方法 我认为最有希望的是在我的测试片段中使用viewModelFactory生成器,比如ViewModelUtil.createFor(mockedViewModel)在测试片段中使用。但这对我不起作用,在运行startFragment时,在模拟viewModel中创建的测试服务将被生产服务替换,如下所示 我的主应用程序扩展了DaggerApplication(),

在测试期间,我的视图模型仍在使用生产服务,我希望它们使用测试服务。我正在使用robolectric进行测试,但仍然没有找到解决问题的方法

我认为最有希望的是在我的测试片段中使用viewModelFactory生成器,比如
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)
    }