DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

ViewModel Unit Testing Guide - Turbine, MockK & TestDispatcher

Unit Testing ViewModels with Turbine and MockK

Write comprehensive ViewModel tests using modern Kotlin testing tools.

MainDispatcherRule Setup

@get:Rule
val mainDispatcherRule = MainDispatcherRule()

@Test
fun testUserLoading() = runTest {
    // Automatically uses TestDispatchers
}
Enter fullscreen mode Exit fullscreen mode

MockK coEvery/coVerify

val mockRepository = mockk<UserRepository>()
coEvery { mockRepository.fetchUser(any()) } returns User(1, "Alice")

val viewModel = UserViewModel(mockRepository)

coVerify { mockRepository.fetchUser("123") }
Enter fullscreen mode Exit fullscreen mode

Turbine Flow Testing

@Test
fun testUiStateFlow() = runTest {
    turbineScope {
        val uiStateTurbine = viewModel.uiState.testIn(backgroundScope)

        assertEquals(UiState.Loading, uiStateTurbine.awaitItem())
        assertEquals(UiState.Success(user), uiStateTurbine.awaitItem())
        uiStateTurbine.ensureAllEventsConsumed()
    }
}
Enter fullscreen mode Exit fullscreen mode

StateFlow State Transitions

@Test
fun testStateTransitions() = runTest {
    viewModel.loadUser("123")

    advanceTimeBy(100) // Simulate time passage

    assertEquals(User(1, "Alice"), viewModel.user.value)
}
Enter fullscreen mode Exit fullscreen mode

SavedStateHandle Testing

val savedStateHandle = SavedStateHandle(mapOf("userId" to "123"))
val viewModel = UserViewModel(
    repository = mockRepository,
    savedStateHandle = savedStateHandle
)
Enter fullscreen mode Exit fullscreen mode

Test Structure

  1. Setup mocks with coEvery
  2. Create ViewModel with dependencies
  3. Trigger action
  4. Verify state changes with Turbine
  5. Verify interactions with coVerify

Common Assertions

  • awaitItem(): Get next emitted value
  • awaitComplete(): Wait for completion
  • ensureAllEventsConsumed(): Verify no leftover events
  • skipItems(n): Skip n events

Best Practices

  • Test state transitions, not implementation
  • Use Turbine for Flow/StateFlow testing
  • Mock external dependencies
  • Test error cases and edge cases

8 Android app templates on Gumroad

Top comments (0)