我想测试我的视图模型类并遇到以下问题。所以,这里是我的代码的相关部分:
// ItemsViewModelTest.kt
@ExperimentalPagingApi
@OptIn(ExperimentalCoroutinesApi::class)
class ItemsViewModelTest {
private val testDispatcher = TestCoroutineDispatcher()
private lateinit var database : MyDatabase
private lateinit var fakeItemApi: FakeItemApi
private lateinit var fakeItemRepository: FakeItemRepository
private val itemFactory = itemFactory()
/* here are I create some dummy Items that will be passed to the fake item api -> the itemFactory is just a normal helper class producing items*/
private val dummyItems = listOf(
itemFactory.createItem(name="my first item"),
itemFactory.createItem(name="my second item"),
itemFactory.createItem(name="my third item")
)
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
// create the fake item api class
fakeItemApi = FakeItemApi()
// create the in-memory database
database = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
MyDatabase::class.java).build()
// create the fake item repository simulating the real repository
fakeItemRepository = FakeItemRepository(fakeItemApi, database)
}
@After
fun tearDown() {
Dispatchers.resetMain()
database.clearAllTables()
database.close()
fakeItemApi.clearItemList()
}
@Test
fun getItemTest() = runBlockingTest(testDispatcher){
// pass items to the FakeItemApi
dummyItems.forEach { item -> fakeItemApi.addItem(item) }
val differ = AsyncPagingDataDiffer(
diffCallback = ITEM_COMPARATOR,
updateCallback = noopListUpdateCallback,
mainDispatcher = testDispatcher,
workerDispatcher = testDispatcher
)
// create the viewmodel to test by passing the fake repository
val itemsFragmentViewModel = ItemsFragmentViewModel(fakeItemRepository)
// submitData allows differ to receive data from PagingData, but suspends until
// invalidation, so we must launch this in a separate job.
val job = launch {
itemsFragmentViewModel.getItems().collectLatest { pagingData ->
differ.submitData(pagingData)
}
}
// Wait for initial load to finish.
advanceUntilIdle()
// HERE: differ.snapshot() returns an empty list
assertThat(differ.snapshot()).containsExactly(
dummyItems[0],
dummyItems[1],
dummyItems[2]
)
// runBlockingTest checks for leaking jobs, so we have to cancel the one we started.
job.cancel()
}
}
val noopListUpdateCallback = object : ListUpdateCallback {
override fun onInserted(position: Int, count: Int) {}
override fun onRemoved(position: Int, count: Int) {}
override fun onMoved(fromPosition: Int, toPosition: Int) {}
override fun onChanged(position: Int, count: Int, payload: Any?) {}
}
我的问题是differ.snapshot()
返回一个空列表,因此测试函数中的断言失败。我希望有人可以帮忙。
现在,这里是我的假存储库类和假项目 api 的相关部分,以防您问这些看起来如何:
// FakeItemApi.kt
class FakeItemApi : ItemApi {
// simulates the data we get from server
// when the test runs, this list gets populated with items
private val itemList = mutableListOf<Item>()
fun addItem(item:Item) {
itemList.add(item)
}
fun clearItemList() = itemList.clear()
// just returns an instance of ListOfItemsResponse which contains the simulated items list
override suspend fun getItems(page: Int): ListOfItemsResponse {
return ListOfItemsResponse(
count = itemList.size.toLong(),
listOfItems = itemList)
}
}
// FakeItemRepository.kt
@ExperimentalPagingApi
class FakeItemRepository(
private val fakeItemApi: FakeItemApi,
private val database: MyDatabase
) : ItemRepositoryInterface {
// returns
override fun getItems(): Flow<PagingData<Item>> {
return Pager(
config = PagingConfig(pageSize = PAGE_SIZE, enablePlaceholders = false),
remoteMediator = ItemsRemoteMediator(fakeItemApi, database),
/* A function that defines how to create the PagingSource */
pagingSourceFactory = {database.itemDao().queryItems()}
).flow
}
}
这ItemsRemoteMediator
是我从官方分页项目中借来的一个普通的远程调解器类。为简洁起见,我不在这里包括它。唯一的区别是我将假项目 api 传递给它,以便它应该将虚拟项目插入本地数据库(房间)。
总结一下我的问题:为什么differ.snapshot()
返回一个空列表?
作为灵感,我查看了这个github 项目以及这里的这个 SO 线程,但不知何故我没有为我工作。而不是val differ = AsyncPagingDataDiffer(..)
,我也尝试用ItemsAdapter
(不包括在内,但它也是一个基本的适配器类扩展PagingDataAdapter
)类来测试它,但测试用例也失败了。