Because the Domain layer has zero Android dependencies, it’s trivial to unit test with plain JUnit and MockK for mocking:
class GetPopularMoviesUseCaseTest {
private val repository: MovieRepository = mockk()
private val useCase = GetPopularMoviesUseCase(repository)
@Test
fun `returns success when repository succeeds`() = runTest {
val fakeMovies = listOf(Movie(1, "Inception", 2010))
coEvery { repository.getPopularMovies() } returns NetworkResult.Success(fakeMovies)
val result = useCase()
assertEquals(NetworkResult.Success(fakeMovies), result)
coVerify(exactly = 1) { repository.getPopularMovies() }
}
}
runTest (from kotlinx-coroutines-test) runs suspend test bodies on a controlled test dispatcher, so tests involving coroutines run deterministically and instantly rather than needing real delays.
UI testing a Composable
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun movieCard_displaysTitle() {
composeTestRule.setContent {
MovieCard(movie = Movie(1, "Inception", 2010), onClick = {})
}
composeTestRule.onNodeWithText("Inception").assertIsDisplayed()
}
A healthy test pyramid for a production app has many fast unit tests on the Domain/Data layers, fewer Compose UI tests on individual screens, and only a handful of full end-to-end tests.
- Image
- SKU
- Rating
- Price
- Stock
- Availability
- Add to cart
- Description
- Content
- Weight
- Dimensions
- Additional information