You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置dagger-android 2.15后,编写Espresso测试时如何实现Mock?

我之前也踩过这个坑!用普通Dagger2的时候,在Application里握个AppComponent的引用,Espresso测试时直接替换就行,别提多方便了。但换成dagger-android 2.15之后,它把组件初始化的逻辑都隐式处理了,代码是简洁了,可测试的时候想换组件就卡壳了。

先把你提到的Application代码补全下,方便大家理解:

class App : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerAppComponent.factory().create(this)
    }
}

下面给你两个亲测有效的解决思路:

方案一:给Application留个“组件替换口子”

最简单的方式就是把组件创建的逻辑抽成可重写的方法,让测试类能轻松替换:

修改你的生产环境App类:

open class App : DaggerApplication() {
    // 把组件创建逻辑抽成开放方法,默认返回正式组件
    open fun buildAppComponent(): AppComponent {
        return DaggerAppComponent.factory().create(this)
    }

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return buildAppComponent()
    }
}

然后在测试模块里写个TestApp继承它,返回测试专用的组件:

class TestApp : App() {
    override fun buildAppComponent(): AppComponent {
        // 这里返回你提前配置好的测试组件,比如把真实的网络请求换成Mock版本
        return DaggerTestAppComponent.factory().create(this)
    }
}

最后别忘了在测试目录的AndroidManifest.xml里指定使用TestApp作为Application,这样跑Espresso测试时就会自动加载测试组件了。

方案二:用测试规则手动替换注入器

如果不想改动生产代码,也可以通过Espresso的测试规则来手动替换组件。不过这个方式需要你给App类加个小口子:

先修改原App类,允许外部设置自定义注入器:

class App : DaggerApplication() {
    private var customInjector: AndroidInjector<out DaggerApplication>? = null

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        // 优先用自定义注入器,没有的话再用默认的正式组件
        return customInjector ?: DaggerAppComponent.factory().create(this)
    }

    // 给测试用的方法,仅在测试时调用,可加上@VisibleForTesting注解标记
    fun setCustomInjector(injector: AndroidInjector<out DaggerApplication>) {
        this.customInjector = injector
    }
}

然后在测试类里写个自定义测试规则,在启动Activity前替换组件:

class MainScreenTest {
    @get:Rule
    val activityRule = object : ActivityTestRule<MainActivity>(MainActivity::class.java, false, false) {
        override fun beforeActivityLaunched() {
            super.beforeActivityLaunched()
            // 获取Application实例
            val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App
            // 创建测试组件
            val testComponent = DaggerTestAppComponent.factory().create(app)
            // 替换注入器
            app.setCustomInjector(testComponent)
        }
    }

    @Test
    fun testMockDataDisplay() {
        // 启动Activity
        activityRule.launchActivity(null)
        // 这里就可以验证Mock数据的展示逻辑了
    }
}

小提醒

个人更推荐方案一,因为它的侵入性极低,测试代码和生产代码的边界很清晰,符合测试隔离的原则。方案二适合不想改动生产代码的场景,但要注意用注解标记测试专用方法,避免误用到生产逻辑里。

内容的提问来源于stack exchange,提问作者Albert Gao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:39:41