如何从分页3测试分页数据 [英] How To Test PagingData From Paging 3
问题描述
我的 ViewModel 有一个返回 PagingData 流的方法.在我的应用程序中,数据是从远程服务器上获取的,然后保存到 Room (房间的唯一来源):
My ViewModel has a method which returns a flow of PagingData. In my app, the data is fetched from the remote server, which is then saved to Room (the single source of truth):
fun getChocolates(): Flow<PagingData<Chocolate>> {
val pagingSourceFactory = { dao().getChocolateListData() }
return Pager(
config = PagingConfig(
pageSize = NETWORK_PAGE_SIZE,
maxSize = MAX_MEMORY_SIZE,
enablePlaceholders = false
),
remoteMediator = ChocolateRemoteMediator(
api,
dao
),
pagingSourceFactory = pagingSourceFactory
).flow
}
如何测试此方法?我想测试返回的流是否包含正确的数据.
How do I test this method? I want to test if the returning flow contains the correct data.
到目前为止我已经尝试过的:
What I've tried so far:
@InternalCoroutinesApi
@Test
fun getChocolateListReturnsCorrectData() = runBlockingTest {
val chocolateListDao: ChocolateListDao by inject()
val chocolatesRepository: ChocolatesRepository by inject()
val chocolateListAdapter: ChocolateListAdapter by inject()
// 1
val chocolate1 = Chocolate(
name = "Dove"
)
val chocolate2 = Chocolate(
name = "Hershey's"
)
// 2
// You need to launch here because submitData suspends forever while PagingData is alive
val job = launch {
chocolatesRepository.getChocolateListStream().collectLatest {
chocolateListAdapter.submitData(it)
}
}
// Do some stuff to trigger loads
chocolateListDao.saveChocolate(chocolate1, chocolate2)
// How to read from adapter state, there is also .peek() and .itemCount
assertEquals(listOf(chocolate1, chocolate2).toMutableList(), chocolateListAdapter.snapshot())
// We need to cancel the launched job as coroutines.test framework checks for leaky jobs
job.cancel()
}
我想知道自己是否走对了.任何帮助将不胜感激!
I'm wondering if I'm on the right track. Any help would be greatly appreciated!
推荐答案
我发现使用 cashapp中的涡轮会容易得多.( JakeWharton 再次救出:P)
I found using Turbine from cashapp would be much much easier.(JakeWharton comes to rescue again :P)
testImplementation "app.cash.turbine:turbine:0.2.1"
根据您的代码,我认为您的测试用例应如下所示:
According to your code I think your test case should looks like:
@ExperimentalTime
@ExperimentalCoroutinesApi
@Test
fun `test if receive paged chocolate data`() = runBlockingTest {
val expected = listOf(
Chocolate(name = "Dove"),
Chocolate(name = "Hershey's")
)
coEvery {
dao().getChocolateListData()
}.returns(
listOf(
Chocolate(name = "Dove"),
Chocolate(name = "Hershey's")
)
)
launchTest {
viewModel.getChocolates().test(
timeout = Duration.ZERO,
validate = {
val collectedData = expectItem().collectData()
assertEquals(expected, collectedData)
expectComplete()
})
}
}
我还准备了一个基本的ViewModelTest类,用于处理许多设置和tearDown任务:
I also prepare a base ViewModelTest class for taking care of much of setup and tearDown tasks:
abstract class BaseViewModelTest {
@get:Rule
open val instantTaskExecutorRule = InstantTaskExecutorRule()
@get:Rule
open val testCoroutineRule = CoroutineTestRule()
@MockK
protected lateinit var owner: LifecycleOwner
private lateinit var lifecycle: LifecycleRegistry
@Before
open fun setup() {
MockKAnnotations.init(this)
lifecycle = LifecycleRegistry(owner)
every { owner.lifecycle } returns lifecycle
}
@After
fun tearDown() {
clearAllMocks()
}
protected fun initCoroutine(vm: BaseViewModel) {
vm.apply {
setViewModelScope(testCoroutineRule.testCoroutineScope)
setCoroutineContext(testCoroutineRule.testCoroutineDispatcher)
}
}
@ExperimentalCoroutinesApi
protected fun runBlockingTest(block: suspend TestCoroutineScope.() -> Unit) =
testCoroutineRule.runBlockingTest(block)
protected fun launchTest(block: suspend TestCoroutineScope.() -> Unit) =
testCoroutineRule.testCoroutineScope.launch(testCoroutineRule.testCoroutineDispatcher) { block }
}
关于扩展功能 collectData()
,该功能是从另一篇帖子的答案中借来的(谢谢 @Farid !!)
As for extension function collectData()
that's borrowed from answer from another post (Thanks @Farid!!)
和介绍涡轮的幻灯片放映>
And a slide show introducing turbine
这篇关于如何从分页3测试分页数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!