-
Notifications
You must be signed in to change notification settings - Fork 0
Test ViewModel
Ali Sadeghi edited this page Jan 27, 2026
·
7 revisions
Generates ViewModel tests using Turbine for StateFlow testing.
Spawned by: test-orchestrator during /feature-test command
- Initial state (Uninitialized or Loading)
- State transitions (Loading → Success, Loading → Failed)
- Retry flow (Failed → Loading → Success)
- User actions and their effects
- Rapid action debouncing
- Input validation (if applicable)
- Dialog state management (if applicable)
@OptIn(ExperimentalCoroutinesApi::class)
class LoginViewModelTest {
private val testDispatcher = StandardTestDispatcher()
private val repository = mock<LoginRepository>()
private lateinit var viewModel: LoginViewModel
@BeforeTest
fun setup() {
Dispatchers.setMain(testDispatcher)
}
@AfterTest
fun teardown() {
Dispatchers.resetMain()
resetAnswers(repository)
}
private fun createViewModel() {
viewModel = LoginViewModel(repository)
}
@Test
fun `login emits Loading then Success on success`() = runTest {
everySuspend { repository.login(any()) } returns
LoginFixtures.createSuccessUser()
createViewModel()
viewModel.uiModelState.test {
var current = awaitItem()
if (current.state is UiState.Uninitialized) {
current = awaitItem()
}
assertTrue(current.state is UiState.Loading)
viewModel.login("test@example.com", "password")
advanceUntilIdle()
current = expectMostRecentItem()
assertTrue(current.state is UiState.Success)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `retry after failure transitions to Success`() = runTest {
everySuspend { repository.login(any()) } sequentiallyReturns listOf(
LoginFixtures.createFailureUser(),
LoginFixtures.createSuccessUser()
)
createViewModel()
viewModel.uiModelState.test {
// Wait for initial failure
var current = awaitItem()
while (current.state !is UiState.Failed) {
advanceUntilIdle()
current = awaitItem()
}
// Retry
viewModel.retry()
advanceUntilIdle()
current = expectMostRecentItem()
assertTrue(current.state is UiState.Success)
cancelAndIgnoreRemainingEvents()
}
}
}MUST be called immediately after any method that triggers coroutines:
// WRONG - after ViewModel creation
createViewModel()
advanceUntilIdle() // Don't do this!
// CORRECT - after method call
viewModel.retry()
advanceUntilIdle() // Immediately after!Back to Testing Agents | Agents