Charlie
Charlie

Reputation: 1

How am i supposed to do Unit Test for a viewmodel that have a function to get it's token from api?

i've been working on this assignment of mine. to make a unit test on a viewmodel. but the viewmodel actually fetch token from api. is making a dummy for the token right? also i have a problem to make the unit test to work too

The unit test supposed to check when data had been loaded succesfully:

and when story data is unavailable:

-check if the data received is null or empty

under this is the error that came from first unit test im tryin to fix Error Unit Test

this is the unit test

@ExperimentalCoroutinesApi
@RunWith(MockitoJUnitRunner::class)
class MainViewModelTest {
    @get:Rule
    val instantExecutorRule = InstantTaskExecutorRule()

    @get:Rule
    val mainDispatcherRules = MainDispatcherRule()

    @Mock
    lateinit var storyRepository: UserRepository


    @Test
    fun `when Get Quote Should Not Null and Return Data`() = runTest {
        val dummyQuote = DataDummy.generateDummyStoryResponse()
        val data: PagingData<ListStoryItem> = QuotePagingSource.snapshot(dummyQuote)
        val expectedQuote = MutableLiveData<PagingData<ListStoryItem>>()
        expectedQuote.value = data
        val dummyUserModel = UserModel(email = "[email protected]" , token = dummyToken, userId = "232321", name ="Charlie", isLogin = true)
        val dummyFlow = flowOf(dummyUserModel)
        //bug baris 50
        val mainViewModel = MainViewModel(storyRepository)
        Mockito.`when`(storyRepository.getSession()).thenReturn(dummyFlow)
        Mockito.`when`(storyRepository.getStoriesWithPaging(dummyToken)).thenReturn(expectedQuote)


        val actualQuote: PagingData<ListStoryItem> = mainViewModel.stories.getOrAwaitValue()
        val differ = AsyncPagingDataDiffer(
            diffCallback = StoryAdapter.StoryDiffCallback(),
            updateCallback = noopListUpdateCallback,
            workerDispatcher = Dispatchers.Main,
        )
        differ.submitData(actualQuote)

        Assert.assertNotNull(differ.snapshot())
        Assert.assertEquals(dummyQuote.size, differ.snapshot().size)
        Assert.assertEquals(dummyQuote[0], differ.snapshot()[0])

    }
    companion object {
        private const val dummyToken =
            "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyLWRlX29wd1dmN0s4QVhNSTkiLCJpYXQiOjE2NjcwNDYxMzN9._TmFRjqq3BL8R--c1mIDTB2UwaJfFDCv_kt8lxNfnMU"
    }

    @Test
    fun `when Get Quote Empty Should Return No Data`() = runTest {
        val data: PagingData<ListStoryItem> = PagingData.from(emptyList())
        val expectedQuote = MutableLiveData<PagingData<ListStoryItem>>()
        expectedQuote.value = data
        val dummyUserModel = UserModel(email ="[email protected]" , token = dummyToken, userId = "232321", name ="Charlie", isLogin = true)
        val dummyFlow = flowOf(dummyUserModel)
        Mockito.`when`(storyRepository.getSession()).thenReturn(dummyFlow)
        Mockito.`when`(storyRepository.getStoriesWithPaging(dummyToken)).thenReturn(expectedQuote)
        val mainViewModel = MainViewModel(storyRepository)
        val actualQuote: PagingData<ListStoryItem> = mainViewModel.stories.getOrAwaitValue()
        val differ = AsyncPagingDataDiffer(
            diffCallback = StoryAdapter.StoryDiffCallback(),
            updateCallback = noopListUpdateCallback,
            workerDispatcher = Dispatchers.Main,
        )
        differ.submitData(actualQuote)
        Assert.assertEquals(0, differ.snapshot().size)
    }

}

class QuotePagingSource : PagingSource<Int, LiveData<List<ListStoryItem>>>() {
    companion object {
        fun snapshot(items: List<ListStoryItem>): PagingData<ListStoryItem> {
            return PagingData.from(items)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, LiveData<List<ListStoryItem>>>): Int {
        return 0
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LiveData<List<ListStoryItem>>> {
        return LoadResult.Page(emptyList(), 0, 1)
    }
}

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?) {}
}

under this is the viewmodel that i want to make unit test


class MainViewModel(private val repository: UserRepository) : ViewModel() {

    private val _stories = MutableLiveData<PagingData<ListStoryItem>>()
    val stories: LiveData<PagingData<ListStoryItem>> get() = _stories

    private val _isLoading = MutableLiveData<Boolean>()

    fun getSession(): LiveData<UserModel> {
        return repository.getSession().asLiveData()
    }

    private val _userToken = MediatorLiveData<String>()
    val userToken: LiveData<String> get() = _userToken

    init {
        _userToken.addSource(repository.getSession().asLiveData()) { userModel ->
            _userToken.value = userModel.token
        }
    }

    fun getStory() {
        userToken.observeForever { token ->
            _isLoading.value = true
            viewModelScope.launch {
                try {
                    repository.getStoriesWithPaging(token).observeForever { pagingData ->
                        _stories.value = pagingData
                    }
                } catch (e: Exception) {
                    // Tangani error jika ada
                } finally {
                    _isLoading.value = false
                }
            }
        }

    }

    fun logout() {
        viewModelScope.launch {
            repository.logout()
        }
    }

}

please help me. and should i send my github repo to make it clearer?

I have tried to fix the parameter specified as non null by trying to fetch data token from get session() but that creates further problem since the datastore im using is null cause it haven't got login response that return token from api.

Upvotes: 0

Views: 16

Answers (1)

Charlie
Charlie

Reputation: 1

Just Randomly Solved this after 3 match in valorant The main problem comes from this line of code

val mainViewModel = MainViewModel(storyRepository) 

That initiated before

Mockito.when(storyRepository.getSession()).thenReturn(dummyFlow) Mockito.when(storyRepository.getStoriesWithPaging(dummyToken)).thenReturn(expectedQuote)

Which creates the non-null error

Upvotes: 0

Related Questions