覆盖使用@ Component.Factory创建的Dagger2组件/模块

时间:2019-06-11 14:16:43

标签: android android-espresso dagger-2

我正在尝试寻找正确的方法来覆盖Espresso测试中的 Component Module ,同时使用最新的Dagger2 @ strong。@ Component.Factory 功能。 我有以下组件定义:

@Component(
    modules = [SomeModule::class],
    dependencies = [SessionComponent::class]
)
interface MainComponent {
    @Component.Factory
    interface Factory {
        fun create(sessionComponent: SessionComponent): MainComponent
    }
}

SomeModule 的定义是:

@Module
object SomeModule {

    @Provides
    @JvmStatic
    fun some(): Some = SomeImpl()
}

一些是一个接口, SomeImpl 将是其实现。

现在,要加入我们的活动,我们要做:

DaggerMainComponent.factory().create(sessionComponent).inject(this)

我们使用 CustomApp:应用程序

中声明的扩展功能解析 sessionComponent
val Context.sessionComponent: SessionComponent
    get() = App.sessionComponent(this)

现在按照官方指南中的建议进行:https://dagger.dev/testing,我们应该尝试将 MainComponent 替换为 TestMainComponent ,该组件将具有 TestSomeModule 和我们的测试实现。

我最初的想法是朝这个方向发展: 从活动中删除注入,并用将执行此注入的 Injector 对象代替。另外,修改 create()方法并传递 Module

DaggerMainComponent.factory().create(sessionComponent).inject(this)

已移至:

object Injector {
   @VisibleForTesting
   var someModule: SomeModule = SomeModule()

    fun inject(activity: Activity) {
        when (activity) {
            is MainActivity -> {
                DaggerMainComponent.factory().create(App.sessionComponent(activity), someModule).inject(activity)
            }
        }
    }
}

以及新的 Factory 定义:

@Component.Factory
 interface Factory {
  fun create(sessionComponent: SessionComponent, someModule: SomeModule): MainComponent
 }

然后,在活动中的 onCreate()之后,我们只需调用Injector.inject(this)

其背后的想法是,在UI测试中我们可以做到:

@Before
 fun setup() {
  Injector.someModule = TestSomeModule
 }

并以这种方式更改实现。由于 SomeModule 这是一个单例对象,因此我们无法扩展。

这导致我采用以下方法: 该应用程序具有版本调试 buildTypes 。在release和debug文件夹中,我具有 Injector 的真实实现( MainComponent 引用了 SomeModule )。 然后在 androidTest 文件夹中,我有另一个 Injector 对象,但具有以下内容:

object Injector {

    fun inject(activity: Activity) {
        when (activity) {
            is MainActivity -> {
                DaggerTestMainComponent.factory().create(App.sessionComponent(activity)).inject(activity)
            }
        }
    }
}

TestMainComponent

@Component(
    modules = [TestSomeModule::class],
    dependencies = [SessionComponent::class]
)
interface TestMainComponent {
    @Component.Factory
    interface Factory {
        fun create(sessionComponent: SessionComponent): TestMainComponent
    }
}

@Module
object TestSomeModule {
    @Provides
    @JvmStatic
    fun greeter(): Some = TestSomeImpl()
}

这种方法有效,并且gradle用androidTest文件夹中的一个替换了debug文件夹中的 Injector 对象,但是,我想知道是否有更好的方法来避免使用两个 Injector 对象,或者只是更新与测试对象一起使用的 Module 。 任何建议都欢迎!

0 个答案:

没有答案