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

如何在Android Instrumentation Tests中兼容Hilt与非Hilt测试

如何配置Android Instrumentation Tests同时支持Hilt与非Hilt测试

问题背景

原本可正常运行的Jetpack Compose + Espresso测试,在按照谷歌Hilt测试指南添加HiltTestRule并配置自定义CustomTestRunner后,Hilt测试能正常执行,但使用createAndroidComposeRule的非Hilt测试抛出以下错误:

java.lang.IllegalStateException: The component was not created. Check that you have added the HiltAndroidRule.

问题根源在于自定义的CustomTestRunner强制所有测试使用HiltTestApplication,代码如下:

class CustomTestRunner : AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
        return super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}

此前尝试的两种方案均无效:

  • 无法配置多个testInstrumentationRunner,也无法直接从测试向defaultConfig传递标记
  • 尝试通过runnerArgs判断测试注解,但runnerArgs为私有属性,子类无法访问

可行解决方案

方案1:通过反射识别测试注解,动态选择Application

修改CustomTestRunner,利用反射获取当前运行的测试类,判断是否带有Hilt测试注解(如@HiltAndroidTest),动态决定使用的Application:

class CustomTestRunner : AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
        // 获取当前测试类的全限定名
        val testClassName = System.getProperty("android.junit.class")
        return testClassName?.let {
            val testClass = Class.forName(it, false, cl)
            // 仅对标记@HiltAndroidTest的测试使用HiltTestApplication
            if (testClass.isAnnotationPresent(HiltAndroidTest::class.java)) {
                super.newApplication(cl, HiltTestApplication::class.java.name, context)
            } else {
                // 非Hilt测试使用项目原本的Application
                super.newApplication(cl, MyApp::class.java.name, context)
            }
        } ?: super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}

这样只有标记了@HiltAndroidTest的测试会加载HiltTestApplication,非Hilt测试使用原项目的MyApp,避免报错。

方案2:拆分测试源集,独立配置Runner

将Hilt测试与非Hilt测试拆分到不同的测试源集,分别配置对应的测试Runner:

  1. 在项目中新建androidTestHilt测试源集,目录结构与androidTest一致:

    src/
      androidTest/          # 非Hilt测试
      androidTestHilt/      # Hilt测试
        java/
        res/
        AndroidManifest.xml
    
  2. 在Module的build.gradle中配置源集与Runner:

    android {
        sourceSets {
            androidTestHilt {
                java.srcDirs = ['src/androidTestHilt/java']
                res.srcDirs = ['src/androidTestHilt/res']
                manifest.srcFile 'src/androidTestHilt/AndroidManifest.xml'
            }
        }
    
        defaultConfig {
            // 非Hilt测试使用默认Runner或自定义非Hilt Runner
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    
        // 为Hilt测试源集配置自定义Runner
        testVariants.all { variant ->
            if (variant.name.contains("androidTestHilt")) {
                variant.instrumentationRunner = "com.yourpackage.CustomTestRunner"
            }
        }
    }
    

    此方案通过物理拆分测试代码,让两类测试使用各自的Runner,完全隔离配置。

注意事项

  • 方案1需确保@HiltAndroidTest注解已正确引入(依赖hilt-android-testing库)
  • 方案2需要维护两个测试源集,适合测试职责划分清晰的项目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:35:23