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

Robolectric单元测试调用Fragment内getString触发IllegalStateException问题

问题现象

使用Robolectric对Fragment做单元测试时,调用Fragment内部的getString()方法抛出IllegalStateException异常,错误堆栈如下:

Caused by: java.lang.IllegalStateException: Fragment SomeFragment{1df37025} (29efd1d0-77c1-4293-a0f6-b808c7559cf4)} not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:805)
at androidx.fragment.app.Fragment.getResources(Fragment.java:869)
at androidx.fragment.app.Fragment.getString(Fragment.java:891)

业务代码(SomeFragment)

public void someMethod() {
    getString(R.string.some_res)
}

原测试代码

@Before
fun setUp() {
    val activity = Robolectric.buildActivity(SomeActivity::class.java).create().get()
    fragment = SomeFragment()
    fragmentManager = activity.supportFragmentManager
    val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
    fragmentTransaction.add(fragment, null)
    fragmentTransaction.commit()
}

@Test
@Throws(Exception::class)
fun someTest() {
    fragment.someMethod()
}
异常原因

FragmentTransaction.commit()是异步执行逻辑,你在测试代码中调用完commit()后立即触发Fragment的方法,此时事务还未完成调度,Fragment没有完成和宿主Activity的绑定,无法获取到Context实例,调用getString()依赖Context拿资源自然会报错。

修复方案

方案1:立即执行待处理的Fragment事务

在commit()调用后新增一行fragmentManager.executePendingTransactions(),强制主线程立即执行所有待处理的Fragment事务,确保Fragment完成attach后再执行测试逻辑,改动最小,无需调整现有测试结构。
修改后的测试代码如下:

@Before
fun setUp() {
    val activity = Robolectric.buildActivity(SomeActivity::class.java).create().get()
    fragment = SomeFragment()
    fragmentManager = activity.supportFragmentManager
    val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
    fragmentTransaction.add(fragment, null)
    fragmentTransaction.commit()
    // 新增这行
    fragmentManager.executePendingTransactions()
}

@Test
@Throws(Exception::class)
fun someTest() {
    fragment.someMethod()
}

方案2:使用官方推荐的FragmentScenario测试

AndroidX测试库提供的FragmentScenario是官方推荐的Fragment测试组件,会自动处理Fragment的生命周期和事务调度,不需要手动管理Activity和Fragment事务,代码更简洁可靠:

@Before
fun setUp() {
    // 直接启动目标Fragment,自动完成attach逻辑
    scenario = FragmentScenario.launchInContainer(SomeFragment::class.java)
}

@Test
fun someTest() {
    scenario.onFragment { fragment ->
        fragment.someMethod()
    }
}

需要提前在build.gradle中引入Fragment测试依赖:

dependencies {
    debugImplementation "androidx.fragment:fragment-testing:1.5.7"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:06:05