繁体   English   中英

如何对从 Paging 3 返回 PagingSource 的 Room Dao 查询进行单元测试

[英]How to Unit Test a Room Dao Query that Returns a PagingSource From Paging 3

我的问题实际上很笼统。 我想知道如何对从Paging 3返回PagingSourceRoom Dao查询进行单元测试。

我有一个Room Dao查询:

    @Query("SELECT * FROM database")
    fun getChocolateListData(): PagingSource<Int, Chocolate>

我想知道如何对这个查询进行单元测试。

到目前为止我尝试过的(使用内存中的Room数据库进行测试):

@FlowPreview
@Test
fun saveChocolateToDbSavesData() = runBlocking {
    val dao: Dao by inject()

    val chocolate = Chocolate(
        name = "Dove"
    )
    dao.saveChocolate(chocolate) 

    val pagingSourceFactory = { dao.getChocolateListData() }
    val pagingDataFlow: Flow<PagingData<Chocolate>> = Pager(
        config = PagingConfig(
            pageSize = 50,
            maxSize = 200,
            enablePlaceholders = false
        ),
        pagingSourceFactory = pagingSourceFactory
    ).flow

    val chocolateListFlow = pagingDataFlow.testIn(coroutinesTestRule)
    Assert.assertEquals(PagingData.from(listOf(chocolate)), chocolateListFlow.emissions[0])
}

然而,这并没有通过:

junit.framework.AssertionFailedError:预期:androidx.paging.PagingData@7d6c23a1 实际:androidx.paging.PagingData@321123d2

不知道如何正确处理。 任何帮助将不胜感激!

PagingData是内部事件 stream 的包装,您无法直接比较它,并且您得到的错误是按预期抛出引用不等式。

相反,您应该直接查询PagingSource以比较LoadResult.Page中的数据,或者您需要将其连接到演示者 API,例如AsyncPagingDataDifferPagingDataAdapter并使用.snapshot()

val flow = Pager(..).flow
val adapter = MyPagingDataAdapter()
val job = launch {
    flow.collectLatest { adapter.submitData(it) }
}
// Do your asserts here
job.cancel()

如果您需要测试 scope,我建议您使用runBlockingTest库中的 runBlockingTest

要直接查询PagingSource ,它有一个暂停的.load()方法,因此您可以简单地将其包装在runBlockingTest中并断言结果:

@Test
fun test() = runBlockingTest {
  val pagingSource = MyPagingSource()
  val actual = pagingSource.load(LoadParams.Refresh(...))
  assertEquals(actual as? LoadResult.Page)?.data, listOf(...))
}

以防万一您需要模拟 PagingSource:

创建助手 class PagingSourceUtils.kt 示例:

class PagingSourceUtils<T : Any>(
    private val data: List<T>
) : PagingSource<Int, T>() {
    override fun getRefreshKey(state: PagingState<Int, T>): Int? {
        return 0
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
        return LoadResult.Page(
            data = data,
            prevKey = null,
            nextKey = null
        )
    }
}

你的测试.kt

@Test
    fun `should success get Chocolate `() {

         val chocolates = listOf(Chocolate(
             name = "Dove"
         )) 

        runBlocking {
            val tData = PagingSourceUtils(chocolates)
            `when`(dao.getChocolateListData()).thenReturn(tData)

            val data = ...

            val actual = ..

            assertEquals(actual, data)
        }
    }

根据标记为正确的答案,我自己做了,不是很漂亮,但如果有任何反馈我会很高兴,至少可以完成工作,在此先感谢。

fun <PaginationKey: Any, Model: Any>PagingSource<PaginationKey, Model>.getData(): List<Model> {
    val data = mutableListOf<Model>()
    val latch = CountDownLatch(1)
    val job = CoroutineScope(Dispatchers.Main).launch {
        val loadResult: PagingSource.LoadResult<PaginationKey, Model> = this@getData.load(
            PagingSource.LoadParams.Refresh(
                key = null, loadSize = Int.MAX_VALUE, placeholdersEnabled = false
            )
        )
        when (loadResult) {
            is PagingSource.LoadResult.Error -> throw loadResult.throwable
            is PagingSource.LoadResult.Page -> data.addAll(loadResult.data)
        }
        latch.countDown()
    }
    latch.await()
    job.cancel()
    return data
}

所以在你的测试中,你可以像这样使用它

val obtainedData = myDao.getSomePagingSource().getData()

assertEquals(expectedData, obtainedData)

警告:你会看到一个相当长的日志

WARNING: pageSize on the LegacyPagingSource is not set.
When using legacy DataSource / DataSourceFactory with Paging3, page size...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM