Skip to main content

UseCase Tests

This page covers testing patterns for Use Cases. Use cases are tested with Mockito-Kotlin (not MockK) β€” see the Mocking Strategy section for why two libraries are used.

UseCase Testing Patterns​

Use cases contain validation logic and delegate to repositories. They are tested to validate input normalization, validation errors, and correct repository delegation.

class AuthUseCasesTest {

private lateinit var authRepository: AuthRepository

@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
authRepository = mock()
}

@Test
fun `LoginUseCase - normalizes email to lowercase and trims`() = runTest {
val useCase = LoginUseCase(authRepository)
val loginResult = createTestLoginResult()
whenever(authRepository.login("user@example.com", "password123")).thenReturn(loginResult)

useCase(" USER@EXAMPLE.COM ", "password123")

verify(authRepository).login("user@example.com", "password123")
}

@Test(expected = InvalidEmailException::class)
fun `LoginUseCase - throws InvalidEmailException when email is empty`() = runTest {
val useCase = LoginUseCase(authRepository)
useCase("", "password123")
}

@Test
fun `LoginUseCase - returns Requires2FA when 2FA is required`() = runTest {
val useCase = LoginUseCase(authRepository)
whenever(authRepository.login("test@example.com", "password123"))
.thenAnswer { throw TwoFactorRequiredException("temp_token_123", "totp") }

val response = useCase("test@example.com", "password123")

assertTrue(response is LoginResponse.Requires2FA)
assertEquals("temp_token_123", (response as LoginResponse.Requires2FA).tempToken)
}
}

Use cases instantiate the subject under test directly (LoginUseCase(authRepository)) rather than using DI, since use cases are simple classes with a single repository dependency.

For use cases that return Flow emissions, Turbine is used for assertions β€” see Flow Testing with Turbine for the full pattern and examples including RealTimeUseCasesTest and UserProfileInteractor.