← ClaudeAtlas

android-testinglisted

Testing patterns for Android/KMP - ViewModel unit tests with JUnit5, Turbine, AssertK, UnconfinedTestDispatcher, fake repositories, SavedStateHandle, and Compose UI tests. Use this skill whenever writing or reviewing tests for ViewModels, repositories, use cases, or Compose screens. Trigger on phrases like "write a test", "unit test the ViewModel", "test a repository", "Turbine", "fake repository", "UnconfinedTestDispatcher", "runTest", "ComposeTestRule", or "JUnit5".
lenorebreakneck630/claude-zero-to-hero-android-KMP · ★ 1 · Testing & QA · score 64
Install: claude install-skill lenorebreakneck630/claude-zero-to-hero-android-KMP
# Android / KMP Testing ## Stack | Concern | Library | |---|---| | Test framework | JUnit5 | | Assertions | AssertK | | Flow / StateFlow testing | Turbine | | Coroutine testing | `kotlinx-coroutines-test` + `UnconfinedTestDispatcher` | | UI testing | `ComposeTestRule` | --- ## ViewModel Unit Tests ### Setup ```kotlin class NoteListViewModelTest { private val testDispatcher = UnconfinedTestDispatcher() @BeforeEach fun setUp() { Dispatchers.setMain(testDispatcher) } @AfterEach fun tearDown() { Dispatchers.resetMain() } } ``` ### Testing State with Turbine ```kotlin @Test fun `loading notes emits notes in state`() = runTest { val repo = FakeNoteRepository() val viewModel = NoteListViewModel(repo) viewModel.state.test { viewModel.onAction(NoteListAction.OnRefreshClick) assertThat(awaitItem().isLoading).isTrue() assertThat(awaitItem().notes).isNotEmpty() } } ``` ### Testing Events (one-time side effects) ```kotlin @Test fun `clicking note sends NavigateToDetail event`() = runTest { val viewModel = NoteListViewModel(FakeNoteRepository()) viewModel.events.test { viewModel.onAction(NoteListAction.OnNoteClick("123")) assertThat(awaitItem()).isEqualTo(NoteListEvent.NavigateToDetail("123")) } } ``` --- ## Fake Repositories Prefer **fakes** (not mocks) for repository dependencies. A fake is a simple in-memory implementation: ```kotlin class F