Orfeo Ciano
02/23/2021, 3:40 PMViewModel
for UI Events (i.e. show a snackbar or navigate to another screen)
class MyViewModel(
private val shouldGoToX: ShouldGoToXUseCase
) : ViewModel() {
private val eventChannel = BroadcastChannel<MyEvent>(Channel.BUFFERED)
val events = eventChannel.asFlow()
fun onCreate() = viewModelScope.launch {
delay(3_000L)
val navigationEvent = if (shouldGoToX()) {
MyEvent.NavigateToX
} else {
MyEvent.NavigateToY
}
eventChannel.offer(navigationEvent)
}
}
internal sealed class MyEvent {
object NavigateToX : MyEvent()
object NavigateToY : MyEvent()
}
And here is my test class
internal class MyViewModelTest {
@get:Rule
val testInstantTaskExecutorRule = InstantTaskExecutorRule()
@get:Rule
val testCoroutineRule = TestCoroutineRule()
private val shouldGoToX = mockk<ShouldGoToXUseCase>()
private val viewModel = MyViewModel(shouldGoToX)
@Test
fun `GIVEN the user should go to X WHEN starting the screen THEN the user should see the X Screen`() =
testCoroutineRule.runBlockingTest {
//GIVEN
coEvery { shouldGoToX() } returns false
//WHEN
viewModel.onCreate()
val events = viewModel.events.toList()
//THEN
assertEquals(MyEvent.NavigateToX, events.first())
}
}
Few questions:
1. Any observations about the approach (events sent through a BroadcastChannel
?
2. I'm currently getting this error in the tests, but I've correctly set the test coroutines stuff java.lang.IllegalStateException: This job has not completed yet
. Am I doing something wrong there?Casey Brooks
02/23/2021, 4:34 PMChannel(capacity = Channel.BUFFERED)
instead of BroadcastChannel
. Given that they are one-time events, having multiple subscribers could cause the snackbar to show multiple times, or navigation to be attempted multiple times, and a normal Channel will help ensure that doesn’t happen.
I’ve also never had great luck with runBlockingTest
, and usually just use normal runBlocking
in my unit tests instead.Orfeo Ciano
02/23/2021, 4:43 PMCasey Brooks
02/23/2021, 4:44 PMOrfeo Ciano
02/23/2021, 4:49 PMCasey Brooks
02/23/2021, 4:52 PMBroadcastChannel<MyEvent>(Channel.BUFFERED)
with Channel(capacity = Channel.BUFFERED)
, and runBlockingTest
with runBlocking
Orfeo Ciano
02/23/2021, 4:56 PM