android - 覆盖使用 @Component.Factory 创建的 Dagger2 组件/模块
问题描述
我正在尝试在使用最新的 Dagger2 @Component.Factory功能时找到在 Espresso 测试中覆盖组件或模块的正确方法。我有以下组件定义:
@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()
}
Some它是一个接口,SomeImpl将是它的实现。
现在,要注入我们的活动,我们只需:
DaggerMainComponent.factory().create(sessionComponent).inject(this)
我们使用 CustomApp中声明的扩展函数解析sessionComponent :Application
val Context.sessionComponent: SessionComponent
get() = App.sessionComponent(this)
现在按照官方指南中的建议:https ://dagger.dev/testing我们应该尝试将MainComponent替换为TestMainComponent,它将在我们的测试实现中包含一个TestSomeModule 。
我最初的想法是朝着这个方向:从 Activity 中删除注入,并用一个可以执行此操作的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)
}
}
}
}
以及新的工厂定义:
@Component.Factory
interface Factory {
fun create(sessionComponent: SessionComponent, someModule: SomeModule): MainComponent
}
然后,在我们刚刚调用的活动中的onCreate()之后Injector.inject(this)
这背后的想法是,在 UI 测试中我们可以这样做:
@Before
fun setup() {
Injector.someModule = TestSomeModule
}
并以这种方式更改实现。它失败了,因为SomeModule它是一个单例对象,我们不能从它扩展。
这导致我采用以下方法:该应用程序具有发布和调试 buildTypes。在发布和调试文件夹中,我有注入器的真正实现( 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 将调试文件夹中的Injector对象替换为 androidTest 文件夹中的对象,但是,我想知道是否有更好的方法来避免为此目的使用两个Injector对象,或者只是更新模块与测试一一起使用。欢迎任何建议!
解决方案
推荐阅读
- sql - 排序表 2 列月和年
- android - SonarQube 没有找到 Kotlin Junit5 测试
- html - 删除一个链接的css悬停效果,同时为其他链接保持相同的悬停效果
- xamarin.forms - 错误以 xamarin 形式引用 objectHydrator
- search - 如何用这些相同的行集替换所有重复的行集但已修改 - 一次?
- assembly - 为什么 rax 寄存器中没有显示任何值?
- php - SQL 没有提供正确的结果。(使用 PHP)
- android - 设置垂直 RecyclerView 高度只对应 N 个项目高度
- java - 搜索 FireBase 实时数据库
- angular - 基于所选选项的角度条件渲染