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

Hilt仪器测试绑定两个ViewModel报错问题求助

解决Hilt仪器测试中"The component was not created"错误

针对你遇到的问题,以下是具体的修复步骤:

1. 调整Rule执行顺序与Activity启动时机

ActivityScenarioRule在初始化时会直接启动Activity,但此时Hilt组件还未创建(hiltRule.inject()还没执行),导致依赖注入失败。需要改为在setup()方法中手动启动Activity:

@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)

@get:Rule(order = 1)
val setupRepoRule = SetupRepoRule(ApplicationProvider.getApplicationContext())

// 改为lateinit,避免提前初始化
private lateinit var activityScenario: ActivityScenario<TourActivity>

在setup()中启动Activity(必须在hiltRule.inject()之后):

@Before
fun setup() {
    hiltRule.inject()
    activityScenario = ActivityScenario.launch(TourActivity.createIntent(context))
    // 其他初始化逻辑...
}

2. 修正Mock对象的初始化

@Mock注解需要配合Mockito初始化逻辑才能生效,在setup()开头添加:

MockitoAnnotations.openMocks(this)

或者添加MockitoRule简化配置:

@get:Rule(order = -1)
val mockitoRule = MockitoJUnit.rule()

3. 修正@BindValue的ViewModel声明

@BindValue的属性需使用lateinit var,确保Hilt能正确识别并替换依赖,同时在setup()中完成ViewModel初始化:

@BindValue
lateinit var viewModel: TourViewModel

@BindValue
lateinit var userInactivityViewModel: UserInactivityViewModel

@Before
fun setup() {
    MockitoAnnotations.openMocks(this)
    hiltRule.inject()
    
    viewModel = TourViewModel(
        userDataRepo = userDataRepo,
        scheduler = Schedulers.computation()
    )
    userInactivityViewModel = UserInactivityViewModel(
        authTokenData = authTokenRepo,
        scheduler = Schedulers.computation(),
        tokenRepo = tokenRepo
    )
    // 其他逻辑...
}

4. 避免提前获取Context

不要在类属性初始化阶段直接获取Context,改为使用lazy延迟加载:

private val context: Context by lazy {
    ApplicationProvider.getApplicationContext()
}

private val targetContext: Context by lazy {
    InstrumentationRegistry.getInstrumentation().targetContext
}

完整修复后的代码示例

@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class TourActivityUat {

    private val context: Context by lazy {
        ApplicationProvider.getApplicationContext()
    }

    private val targetContext: Context by lazy {
        InstrumentationRegistry.getInstrumentation().targetContext
    }

    @get:Rule(order = 0)
    var hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 1)
    val mockitoRule = MockitoJUnit.rule()

    @get:Rule(order = 2)
    val setupRepoRule = SetupRepoRule(context)

    private lateinit var activityScenario: ActivityScenario<TourActivity>

    @Mock
    private lateinit var userDataRepo: UserDataRepo

    @Mock
    private lateinit var authTokenRepo: AuthTokenData
    
    private val tokenRepo by lazy {
        TokenRepository(cookieJar = ClearableCookieJarTest(context))
    }

    @BindValue
    lateinit var viewModel: TourViewModel

    @BindValue
    lateinit var userInactivityViewModel: UserInactivityViewModel

    @Before
    fun setup() {
        hiltRule.inject()

        // 初始化ViewModel
        viewModel = TourViewModel(
            userDataRepo = userDataRepo,
            scheduler = Schedulers.computation()
        )
        userInactivityViewModel = UserInactivityViewModel(
            authTokenData = authTokenRepo,
            scheduler = Schedulers.computation(),
            tokenRepo = tokenRepo
        )

        // 启动Activity
        activityScenario = ActivityScenario.launch(TourActivity.createIntent(context))

        // Mock数据
        val notificationsResponse = NotificationResponse.test(
            messages = 4,
            documents = 0
        )
        whenever(userDataRepo.notifications).doReturn(Observable.just(notificationsResponse))
        whenever(userDataRepo.relationshipIds).doReturn(Single.just(listOf(1L)))
        whenever(userDataRepo.fetchNotifications(any())).doReturn(Completable.complete())
        whenever(userDataRepo.firstName).doReturn(Single.just("Kristy"))

        context.saveTourVisitedStatus(false)
    }

    // 测试方法...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:06:27