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

Android测试中如何创建Foo对象的PagedList?

解决PagedList测试的两个问题:可行性与实例构造

针对你遇到的PagedList测试问题,我来一步步帮你梳理清楚:

1. 这种测试方式完全可行!

只要你能构造出合法的PagedList<Foo>测试实例,就可以用Mockito(或其他Mock框架)来Stub仓库的getFoos()方法,让它返回包含测试数据的Observable。这样ViewModel就能拿到模拟数据,你也能顺利完成端到端的UI验证,确认Fragment/Activity能正确显示Foo列表。

2. 如何创建测试用的PagedList

PagedList的构造需要依赖PagedList.Config和DataSource,下面提供两种实用的实现方式:

方法一:手动构造基础测试实例

首先定义测试用的Config,尽量和生产环境的配置保持一致:

// 匹配你生产代码中的PAGED_LIST_CONFIG参数
val testPagedConfig = PagedList.Config.Builder()
    .setPageSize(20)
    .setEnablePlaceholders(false) // 测试场景下建议关闭占位符,避免额外逻辑干扰
    .setInitialLoadSizeHint(20)
    .build()

然后实现一个Fake DataSource,用于返回固定的测试数据(这里以PageKeyedDataSource为例,你可以根据实际使用的DataSource类型调整):

class FakeFooDataSource(private val testItems: List<Foo>) : PageKeyedDataSource<Int, Foo>() {
    // 返回初始加载的测试数据
    override fun loadInitial(
        params: LoadInitialParams<Int>,
        callback: LoadInitialCallback<Int, Foo>
    ) {
        callback.onResult(testItems, null, 1)
    }

    // 测试场景下不需要加载更多,直接返回空列表
    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Foo>) {
        callback.onResult(emptyList(), null)
    }

    // 同理,不需要向前加载
    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Foo>) {
        callback.onResult(emptyList(), null)
    }
}

最后用PagedList.Builder组装出测试实例:

// 构造测试用的Foo列表
val testFoos = listOf(Foo(id = 1, name = "Test Foo 1"), Foo(id = 2, name = "Test Foo 2"))
val fakeDataSource = FakeFooDataSource(testFoos)

// 生成最终的测试PagedList
val TEST_PAGED_LIST_OF_FOOS = PagedList.Builder(fakeDataSource, testPagedConfig)
    .setNotifyExecutor(Executors.newSingleThreadExecutor())
    .setFetchExecutor(Executors.newSingleThreadExecutor())
    .build()

方法二:封装成工具函数复用

为了避免重复代码,你可以把上面的逻辑封装成一个工具函数:

fun createTestPagedList(foos: List<Foo>): PagedList<Foo> {
    val config = PagedList.Config.Builder()
        .setPageSize(20)
        .setEnablePlaceholders(false)
        .build()
    
    val dataSource = object : PageKeyedDataSource<Int, Foo>() {
        override fun loadInitial(
            params: LoadInitialParams<Int>,
            callback: LoadInitialCallback<Int, Foo>
        ) = callback.onResult(foos, null, 1)

        override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Foo>) = callback.onResult(emptyList(), null)

        override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Foo>) = callback.onResult(emptyList(), null)
    }

    return PagedList.Builder(dataSource, config)
        .setNotifyExecutor(Executors.newSingleThreadExecutor())
        .setFetchExecutor(Executors.newSingleThreadExecutor())
        .build()
}

之后在测试代码里就能直接调用:

val testFoos = listOf(Foo(1), Foo(2))
val TEST_PAGED_LIST_OF_FOOS = createTestPagedList(testFoos)
`when`(repository.getFoos()).thenReturn(Observable.just(TEST_PAGED_LIST_OF_FOOS))

额外测试注意事项

  • 调度器处理:由于RxJava默认使用异步调度器,测试时可能会导致时序问题,建议在测试初始化时替换为同步调度器:
    @Before
    fun setupRxSchedulers() {
        RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
        RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
    }
    
  • 模拟加载状态:如果需要测试加载更多、空状态或错误场景,可以修改Fake DataSource的loadAfter方法,比如返回更多数据、抛出异常,来覆盖不同的业务场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:14:43