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

Android Paging3:如何测试返回Pager的Repository并断言PagingData内容

测试Paging3 Repository中PagingData的内容数量

我已经实现了基于Android Paging3库的Repository,想测试自己的Repository实现。虽然看过官方的Paging3测试文档,但里面只有理论内容。

我的Repository代码如下:

class RepositoriesRepositoryImpl @Inject constructor(
    @IoCoroutineDispatcher private val ioCoroutineDispatcher: CoroutineDispatcher,
    private val service: GithubService,
    private val database: RepositoriesDatabase
) : RepositoriesRepository {
    @OptIn(ExperimentalPagingApi::class)
    override suspend fun fetchRepositories() = withContext(ioCoroutineDispatcher) {
        return@withContext Pager(config = PagingConfig(
            pageSize = NETWORK_PAGE_SIZE, enablePlaceholders = false
        ),
            remoteMediator = GithubRemoteMediator(ioCoroutineDispatcher, service, database),
            pagingSourceFactory = { database.repositoriesDao().allRepositories() }).flow
    }

    companion object {
        const val NETWORK_PAGE_SIZE = 10
    }
}

我的测试类代码如下:

@ExperimentalCoroutinesApi
class RepositoriesRepositoryTest {
    private lateinit var sut: RepositoriesRepository
    private val testDispatcher = UnconfinedTestDispatcher()
    private val fakeGithubService: GithubService = mock {
        onBlocking { fetchRepos(any(), any()) } doSuspendableAnswer {
            Response.success((listOf()))
        }
    }
    private val inMemoryDatabase = Room.inMemoryDatabaseBuilder(
        ApplicationProvider.getApplicationContext(), RepositoriesDatabase::class.java
    ).build()

    @Before
    fun setup() {
        sut = RepositoriesRepositoryImpl(testDispatcher, fakeGithubService, inMemoryDatabase)
    }

    @Test
    fun test1() = runTest {
        sut.fetchRepositories().test {
            val item: PagingData<Repository> = awaitItem()
            assertNull(item)
        }
    }
}

现在我希望断言PagingData的内容,验证其中是否包含预期数量的Repository数据,请问该如何实现?


解决方案

要断言PagingData中的内容数量,核心是将流式的PagingData转换为可直接操作的普通列表,同时需正确模拟依赖并触发完整的数据加载流程,具体实现如下:

1. 模拟返回预期数量的测试数据

修改FakeGithubService的Mock逻辑,生成指定数量的模拟Repository对象,为断言提供基础数据:

private val fakeGithubService: GithubService = mock {
    onBlocking { fetchRepos(any(), any()) } doSuspendableAnswer {
        // 生成10条模拟数据,与Repository中定义的NETWORK_PAGE_SIZE一致
        val testRepos = List(10) { index ->
            Repository(
                id = index.toLong(),
                name = "TestRepo_$index",
                // 补充Repository类所需的其他必填字段
            )
        }
        Response.success(testRepos)
    }
}

2. 借助Paging测试工具转换PagingData

Paging3提供了专门的测试库,可通过snapshot()方法快速将PagingData转换为包含所有加载数据的快照列表:
首先添加测试依赖(版本需与你的Paging3主库版本一致):

androidTestImplementation "androidx.paging:paging-testing:3.2.1"

然后修改测试方法:

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun fetchRepositories_returnsExpectedItemCount() = runTest(testDispatcher) {
    // 获取第一页PagingData
    val pagingData = sut.fetchRepositories().first()
    
    // 将PagingData转换为快照列表
    val loadedItems = pagingData.snapshot().items
    
    // 断言数据数量符合预期
    assertEquals(10, loadedItems.size)
}

3. 手动收集PagingData内容(无需额外依赖)

如果不想引入测试库,可通过嵌套collect操作手动收集PagingData中的所有项:

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun fetchRepositories_returnsExpectedItemCount() = runTest(testDispatcher) {
    val collectedItems = mutableListOf<Repository>()
    
    sut.fetchRepositories().collect { pagingData ->
        pagingData.collect { repo ->
            collectedItems.add(repo)
        }
    }
    
    // 断言收集到的数据数量符合预期
    assertEquals(10, collectedItems.size)
}

4. 完善测试生命周期

为避免测试数据污染,在每个测试结束后关闭内存数据库:

@After
fun teardown() {
    inMemoryDatabase.close()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:25:20