0

我想测试我的视图模型类并遇到以下问题。所以,这里是我的代码的相关部分:

// 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)类来测试它,但测试用例也失败了。

4

0 回答 0