Jona
Jona

Reputation: 283

How to write unit tests for paging library in android

I need to write unit tests for doing a paginated network request. First I implemented paging library logic to retrieve the data. I created a data source class and a repository class to get data from the network request.

This is my data source class

class ListDataSource(
private val networkService: NetworkService,
private val searchKey: String) : PagingSource<Int, ListItem>() {

override fun getRefreshKey(state: PagingState<Int, ListItem>): Int? {
    return state.anchorPosition?.let { anchorPosition ->
        state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)
            ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
    }
}

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ListItem> {
    val pageNumber: Int = params.key ?: 0
    return try {
        val response = networkService.getList(
            searchTerm = searchKey,
            page = pageNumber,
            size = 30
        )

        val listItems = response.response?.list
        val nextKey = listItems?.let { nonNullList ->
            if (nonNullList.size < 30) {
                null
            } else {
                pageNumber + 1
            }
        } ?: run {
            null
        }

        LoadResult.Page(
            data = listItems.orEmpty(),
            prevKey = if (pageNumber == 0) null else pageNumber - 1,
            nextKey = nextKey
        )
    } catch (exception: Exception) {
        LoadResult.Error(exception)
    }
}}

This is my repository class

class ListPagingRepository(private val service: NetworkService) {

private lateinit var pager: Pager<Int, ListItem>
private lateinit var pagingSource: ListDataSource

fun getListPager(): Pager<Int, ListItem> {
    return pager
}

fun isPagerInitialized(): Boolean = this::pager.isInitialized

fun createSource(searchTerm: String) {
    pagingSource = ListDataSource(service, searchTerm)
}

fun createPager() {
    pager = Pager(
        config = PagingConfig(
            initialLoadSize = 15,
            pageSize = 15,
            enablePlaceholders = false,
            prefetchDistance = 2
        ),
        pagingSourceFactory = { pagingSource }
    )
}}

Inside my viewmodel I the function to do the network call is:

fun getPaginatedList(searchTerm: String): Flow<PagingData<ListItem>> {
    listPagingRepository.createSource(searchTerm)
    listPagingRepository.createPager()

    return if (listPagingRepository.isPagerInitialized()) {
        listPagingRepository
            .getListPager()
            .flow
            .cachedIn(viewModelScope)
            .map { pagingData -> pagingData.map { listMapper.map(it) } }
    } else emptyFlow()
}

How can I test this network request? Searched for 2 days but nothing that I found helped me.

Upvotes: 0

Views: 664

Answers (1)

Matt Grier
Matt Grier

Reputation: 254

You should test your implementation, with mocked network responses. An example of such a test with MockK as the mocking framework :

@Test
fun `verify error return from load() when a (types of responses you expect to potentially receive) response is returned` () = runTest {
   
    val mockNetworkService = mockk<NetworkService>(relaxed = true, relaxedUnitFun = true)
   
    val testParams = LoadParams(1, false)
   
    every { mockNetworkService.getList(any(), any(), any()) } returns LoadResponse.Error(YourExpectedException)
   
    val result = ListDataSource(mockNetworkService, "test search").load(testParams)

    assertEquals(LoadResponse.Error(YourExpectedException), result)

}

Upvotes: 0

Related Questions