android - 在 Espresso 中使用 Dagger

标签 android kotlin android-espresso dagger-2 dagger

我计划在我的多模块应用程序上创建 Espresso 测试,我即将创建第一个 Espresso 测试,但我看到的是我的应用程序上没有 AppComponent 我可以在哪里伪造它。因为我想在我的功能模块上添加测试,所以我将从现在开始在那里创建 TestAppTestRunner

我的功能模块上有一个 FeatureComponent,它是通过 App 中的 ComponentFactory 注入(inject)的,所以我想的是创建一个这样的类:

@Component (
     dependencies = [ MoreComponents::class],
     modules = [ DataSourceModule::class ]
)
interface FeatureOneComponent { 

    fun activityOneSubComponent(): FeatureOneActivity.Component.Factory
    fun activityTwoSubComponent(): FeatureTwoActivity.Component.Factory

    @Component.Factory
    interface Factory {
        fun create(
            dependencies
        ):FeatureOneComponent
    }
}

interface FeatureOneProvider {
    fun getFeatureOneComponent(): FeatureOneComponent
}


///ACTIVITY

class FeatureOneActivity : AppCompatActivity() {

    //this comes from Subcomponent is what I want to MOCK 
    @Inject lateinit var presenter

    //these comes from the factory and I have it mocked
    @Inject lateinit var manager

    override fun onCreate(){
        (applicationContext as FeatureOneProvider).getFeatureOneComponent().activityOneSubComponent().create(this).inject(this)
    }
}

@Subcomponent(modules = [ActivityOneModule::class]) <--- THIS I WANT TO MOCK
interface Component {
    fun inject(activity: FeatureOneActivity)

    @SubComponent.Factory
    interface Factory {
        fun create(@BindsInstance activity: FeatureOneActivity): Component
    }
}

@Module
interface ActivityOneModule {
    @Binds
    fun bindPresenter(impl: PresenterImpl): Contract.Presenter    
}

测试

class MyTestApp : Application(), FeatureOneProvider {

    override fun getFeatureOneComponent(): FeatureOneComponent {
        return DaggerMockFeatureOneComponent.create()
    }
}

@Component(
    modules = [MockFeatureOneModules::class]
)
interface MockFeatureOneComponent : FeatureOneComponent {
   

    //I NEED TO MOCK THE SUBCOMPONENT WITH `MockSubcomponent`
}

@Component 
object MockFeatureOneModules {

    @Provides
    fun providesManager() : MyManager = mock(MyManager)
}

//I want to use this module to replace the subcomponent of my activity
@Module
object MockSubcomponent() {
  @Provides
  fun providesFakePresenter() : FeatureOneContract.Presenter = mock { FeatureOneContract.Presenter::class.java }
}

更好地理解问题

当我运行我的测试并放置一个调试器点时,我看到除了 Presenter 之外的所有东西都被模拟了,那是因为 Presenter 在

@Subcomponent(modules = [ActivityOneModule::class]
interface Component {
    fun inject(activity: FeatureOneActivity)

    @SubComponent.Factory
    interface Factory {
        fun create(@BindsInstance activity: FeatureOneActivity): Component
    }
}

@Module
interface ActivityOneModule {
    @Binds
    fun bindPresenter(impl: PresenterImpl): Contract.Presenter    
}

在我的测试组件中,我无权“覆盖”这个子组件,所以除了这个子组件之外的所有东西都被模拟了,我需要这个模拟。

最佳答案

我不知道这是否是最好的主意,但如果我没有误解你的话,你希望这个 Presenter 返回一个 mock {}。你可以做的改变是:

  1. 在您的 TestComponent 中,将 interface 更改为 abstract class
  2. 复制您的子组件并从真实的子组件扩展
@Component(
    modules = [MockFeatureOneModules::class]
)
abstract class MockFeatureOneComponent : FeatureOneComponent {
   

    abstract fun subcomponent() : MockComponent.FactoryMock

    override fun activityOneSubComponent(): FeatureOneActivity.Component.Factory {
        return subcomponent()
    }

    @Subcomponent
    interface MockComponent : FeatureOneActivity.Component { 
       @Subcomponent.Factory
       interface FactoryMock : FeatureOneActivity.Component.Factory {
         override fun create....
       }
    }
}

就是这样,它应该可以工作。

关于android - 在 Espresso 中使用 Dagger,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67094274/

相关文章:

kotlin - 如何使用不同数据类的属性更新 kotlin 数据类

android - Espresso + Junit4 - 在运行所有测试之前登录一次

Android 支持存储库未显示在 Android Studio SDK 管理器中

android - 使用 Espresso on Emulator 在 Android Studio 中测试互联网连接错误处理

android - 如何将 ActionBarCompat Activity 显示为在 AndroidManifest.xml 中设置其主题的对话框?

javascript - 跨 Android 设备的页面缩放问题

android - Android Instant Apps 可以与 Hybrid 应用程序集成吗?

java - Android 以编程方式添加的按钮具有匹配父级宽度和高度

android - runInTransaction block 内的挂起方法

android - 获取空值作为响应