I am very new in Unit testing , i am trying to test my flow using Turbine library, it is not emitting all value, here is my test
fun `send function should emit Loading and Content states`() = runTest {
// Arrange
val userProfile = UserProfile(login = "test_login")
val contentState = UiState.Content(userProfile)
coEvery {
fakeRepository.getDetail(any())
} returns userProfile
// Act
viewModel.send(userProfile.login!!)
// Assert
testScheduler.advanceUntilIdle()
viewModel.uiState.test {
assertEquals(UiState.Loading, awaitItem())
assertEquals(contentState, awaitItem())
cancelAndIgnoreRemainingEvents()
}
}
and ViewModel is here, keep failing with reason
Expected UiState$Loading Actual :Content
viewModelScope.launch(dispatchers.main) {
flow {
emit(UiState.Loading)
val mResponse = userRepository.getDetail(login = login)
emit(UiState.Content(mResponse))
}.catch {
UiState.Error(it.message.toString())
it.printStackTrace()
}.flowOn(dispatchers.main).collect {
_uiState.value = it
}
}
Finally I got solution of my problem, I changed my dispatcher from UnConfinedTestDispatcher to StandardTestDispatcher, it starts working
standardtestdispatcher and unconfinedtestdispatcher
Here is my test code:
@OptIn(ExperimentalCoroutinesApi::class)
class TestDispatchers : DispatcherProvider {
private val testDispatcher = StandardTestDispatcher()
override val main: CoroutineDispatcher
get() = testDispatcher
override val io: CoroutineDispatcher
get() = testDispatcher
override val default: CoroutineDispatcher
get() = testDispatcher
}
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(MockitoJUnitRunner::class)
class UserProfileViewModelTest {
// private var fakeRepository = FakeRepository()
private val testDispatchers = TestDispatchers()
private val fakeRepository = mockk<UserRepository>()
private val fakeDB = mockk<IRoomdatabase>()
private val viewModel =
UserProfileViewModel(
dispatchers = testDispatchers,
userRepository = fakeRepository,
userDatabase = fakeDB
)
//private val coroutineScope = TestScope(testDispatchers.main)
@Before
fun setUP() {
Dispatchers.setMain(testDispatchers.main)
}
@Test
fun `send function should emit Loading and Content states`() = runTest {
// Arrange
val login = "test_login"
val userProfile = UserProfile(login = login)
val contentState = UiState.Content(userProfile)
coEvery {
fakeRepository.getDetail(login)
} returns userProfile
viewModel.send(userProfile.login!!)
// Assert
assertTrue(viewModel.uiState.value == UiState.Empty)
viewModel.uiState.test {
// coroutineScope.testScheduler.advanceUntilIdle()
assertEquals(UiState.Empty, awaitItem())
assertEquals(UiState.Loading, awaitItem())
assertEquals(contentState, awaitItem())
//cancelAndIgnoreRemainingEvents()
}
coVerify { fakeRepository.getDetail(login) }
}