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

Dagger-Hilt+Jetpack集成:Robolectric测试中无法创建ViewModel实例

解决Robolectric测试中Hilt+ViewModelInject的创建失败问题

看起来你遇到的问题是Hilt在Robolectric测试环境中没有正确注入ViewModel的依赖,导致无法创建ViewModel实例。我们一步步来修复这个问题:

1. 核心问题分析

你的测试代码存在几个关键问题:

  • 同时使用了HiltAndroidRule和普通的IntentsTestRule,后者不会与Hilt的依赖注入流程集成,导致Activity启动时Hilt还没完成依赖绑定。
  • Mock的authenticationRepository没有被Hilt识别,ViewModel尝试创建真实的Repository实例(而测试环境中可能没有配置这个实例的注入)。
  • 自定义的TestApplication实现过于复杂,没有正确集成Hilt的测试组件。

2. 修复步骤

步骤1:修正测试类的规则与依赖绑定

替换普通的IntentsTestRule,改用Hilt兼容的方式启动Activity,并将mock的Repository绑定到Hilt组件:

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
@HiltAndroidTest
class SplashActivityTest {
    // 使用@BindValue将mock实例绑定到Hilt测试组件
    @BindValue
    @JvmField
    val authenticationRepository: AuthenticationRepository = mockk(relaxed = true)

    @get:Rule
    val hiltRule = HiltAndroidRule(this)

    private lateinit var activity: SplashActivity

    @Before
    fun setup() {
        // 初始化Hilt依赖注入
        hiltRule.inject()
        // 手动构建并启动Activity,确保Hilt注入完成后再创建Activity
        val intent = Intent(ApplicationProvider.getApplicationContext(), SplashActivity::class.java)
        activity = Robolectric.buildActivity(SplashActivity::class.java, intent)
            .create()
            .get()
    }

    @Test
    fun testViewModelInitialization() {
        // 验证ViewModel能正常创建
        assertNotNull(activity.viewModel)
    }
}

步骤2:简化TestApplication(或使用HiltTestApplication)

如果你不需要复杂的自定义Application逻辑,直接使用Hilt官方提供的HiltTestApplication即可,它已经内置了Hilt测试所需的组件管理逻辑。

如果必须自定义TestApplication,只需添加@HiltAndroidApp注解,Hilt会自动生成所需的组件代码:

@HiltAndroidApp
class TestApplication : MultiDexApplication() {
    override fun onCreate() {
        super.onCreate()
        JodaTimeAndroid.init(this)
    }
}

然后在测试类的@Config中指定application = TestApplication::class。

步骤3:统一Hilt依赖版本

你的依赖配置中混合了固定版本2.28和变量$hilt_version,这可能导致版本冲突。确保所有Hilt/Dagger依赖使用同一版本,比如:

// 根build.gradle定义版本
ext.hilt_version = "2.28"

// 模块build.gradle生产依赖
implementation "com.google.dagger:dagger:$hilt_version"
kapt "com.google.dagger:dagger-compiler:$hilt_version"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha01"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

// 测试依赖
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
testImplementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"
kaptTest "androidx.hilt:hilt-compiler:1.0.0-alpha01"

3. 为什么这样能解决问题?

  • @BindValue会将你的mock Repository实例注入到Hilt的测试组件中,当ViewModel通过@ViewModelInject构造时,Hilt会自动提供这个mock实例,而不是尝试创建真实的Repository。
  • HiltAndroidRule配合inject()方法确保在Activity创建前完成所有依赖注入,这是Hilt测试的标准流程。
  • 使用Robolectric的buildActivity手动启动Activity,能控制启动时机,确保Hilt已经准备好依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:52:55