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

带RecyclerView与DataBinding的Fragment Espresso测试加载卡顿问题排查

问题分析与解决方案

问题拆解

  1. 测试卡在加载状态:loadingLiveDataMock未设置初始值,导致加载进度条一直显示,Espresso等待视图稳定时持续卡住;同时Adapter的Binding创建被mock破坏,RecyclerView无法完成初始化,进一步加剧卡顿。
  2. ItemAuthorBinding实例化错误:DataBinding自动生成的ItemAuthorBinding类没有公共无参构造函数,mockk/spyk无法通过默认构造函数创建代理对象,抛出Can't instantiate proxy via default constructor异常。

解决方案

1. 修复加载卡顿问题

在测试初始化阶段,给LiveData设置明确的初始值,让视图快速进入稳定状态:

@Before
fun setup() {
    // 移除破坏Adapter初始化的DataBinding mock
    // setupDataBindingMocks() 

    // 初始化加载状态为结束,隐藏进度条
    loadingLiveDataMock.value = false
    // 提前设置空作者列表,触发Adapter更新
    authorsLiveDataMock.value = emptyList()

    viewModelMock = mockk<HomeViewModel> {
        every { getGreatestAuthorsLiveData() } returns authorsLiveDataMock
        every { fetchGreatestAuthors() } just Runs // 无需重复postValue
        every { getLoadingLiveData() } returns loadingLiveDataMock
    }
}

2. 解决ItemAuthorBinding实例化问题

不要mockDataBindingUtil.inflate方法,让Adapter真实创建ViewHolder和Binding实例。仪器化测试应优先使用真实视图层级,仅在必要时进行mock。如果必须验证Binding的行为,可以通过真实实例创建spyk:

private fun setupDataBindingMocks() {
    mockkStatic(DataBindingUtil::class)
    // 使用真实LayoutInflater创建Binding实例,再包装为spyk
    val context = ApplicationProvider.getApplicationContext<Context>()
    val realBinding = ItemAuthorBinding.inflate(LayoutInflater.from(context))
    val mockBinding = spyk(realBinding)
    
    every {
        DataBindingUtil.inflate<ItemAuthorBinding>(
            any(),
            eq(R.layout.item_author),
            any(),
            eq(false)
        )
    } returns mockBinding.apply {
        every { root } returns mockk(relaxed = true)
    }
}

注:使用ApplicationProvider需依赖androidx.test:core库

3. 优化测试逻辑

如果仅验证标题是否显示,无需mock Adapter相关逻辑,让Fragment正常执行初始化流程即可,测试会更稳定:

@Test
fun whenViewCreated_shouldDisplayExpectedViews() {
    launchFragmentInContainer<HomeFragment>(
        factory = MainFragmentFactory(viewModelMock)
    )
    // 直接验证目标视图可见性
    Espresso.onView(withId(R.id.fragmentHomeAuthorsTitle))
        .check(matches(isDisplayed()))
}

关键注意事项

  • DataBinding生成的Binding类无法通过无参构造函数mock,必须通过真实创建流程或指定构造参数生成实例。
  • 仪器化测试中尽量减少不必要的mock,避免破坏视图层级的正常初始化逻辑。
  • 必须确保LiveData的初始值设置正确,防止视图长期处于加载状态导致Espresso阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:27:24