Lewati ke konten utama

Unit Testing

Coverage Target​

LayerMin. Coverage
Use Cases90%
ViewModels / Cubits80%
Repositories80%
Utilities / Extensions70%
UI Components50% (widget test)

Framework per Platform​

PlatformFrameworkMocking
AndroidJUnit 5MockK / Mockito-Kotlin
iOSXCTest / Swift TestingProtocol-based mocking
Flutterflutter_testMockito / Mocktail
React NativeJestJest mocks

What to Test​

  • ✅ Use cases (input → output)
  • ✅ ViewModel state transitions
  • ✅ Repository data mapping
  • ✅ Utility functions
  • ✅ Error handling paths
  • ❌ Framework internals
  • ❌ Simple getters/setters

Example​

class GetUserUseCaseTest {
private val repository = mockk<UserRepository>()
private val useCase = GetUserUseCase(repository)

@Test
fun `should return user when repository succeeds`() = runTest {
val expected = User(id = "1", name = "John")
coEvery { repository.getUser("1") } returns Result.success(expected)

val result = useCase("1")

assertTrue(result.isSuccess)
assertEquals(expected, result.getOrNull())
}

@Test
fun `should return failure when repository fails`() = runTest {
coEvery { repository.getUser("1") } returns Result.failure(Exception("Not found"))

val result = useCase("1")

assertTrue(result.isFailure)
}
}
Naming Convention

Test name harus mendeskripsikan behavior, bukan implementasi:

  • ✅ should return user when repository succeeds
  • ❌ testGetUser