๐Ÿงช Testing, Debugging, and Performance

MockK vs Mockito for Kotlin Testing

MockK was built for Kotlin; Mockito comes from Java but works well with mockito-kotlin. Both can mock suspend functions and final classes today. The bigger question is often whether you should be mocking at all.

โœ๏ธ Yunok Tech ๐Ÿ“… Updated โฑ 3 min read ๐ŸŽฏ Intermediate
On this page
  1. The same test in both
  2. Comparison
  3. Often better: fakes
  4. When mocks are the right tool
  5. Team recommendations
  6. Common mistakes
  7. Frequently asked questions
  8. Conclusion

Kotlin classes are final by default, suspend functions take hidden continuation parameters, and top-level functions and objects aren't ordinary Java classes. Early Mockito struggled with all of that, which is why MockK became popular in Android. Both libraries have matured, so the choice is now mostly about style.

The same test in both

MockKKotlin
@Test
fun `refresh shows error when repository fails`() = runTest {
    val repo = mockk<ArticleRepository>()
    coEvery { repo.refresh() } throws IOException()
    every { repo.observeArticles() } returns flowOf(emptyList())

    val vm = ArticlesViewModel(repo)
    vm.refresh(); advanceUntilIdle()

    assertEquals("Couldn't refresh", vm.uiState.value.message)
    coVerify(exactly = 1) { repo.refresh() }
}
Mockito + mockito-kotlinKotlin
@Test
fun `refresh shows error when repository fails`() = runTest {
    val repo = mock<ArticleRepository> {
        onBlocking { refresh() } doThrow IOException()      // doThrow works with checked exceptions too
        on { observeArticles() } doReturn flowOf(emptyList())
    }

    val vm = ArticlesViewModel(repo)
    vm.refresh(); advanceUntilIdle()

    assertEquals("Couldn't refresh", vm.uiState.value.message)
    verifyBlocking(repo, times(1)) { refresh() }
}

Comparison

AspectMockKMockito (+ mockito-kotlin)
Kotlin-first APIYes (every, coEvery, DSL)Via mockito-kotlin extensions
Final classesSupportedSupported (inline mock maker is the default in recent versions)
Suspend functionscoEvery / coVerifyonBlocking / verifyBlocking
Objects, top-level and extension functions, constructorsmockkObject, mockkStatic, mockkConstructorLimited (static mocking via mockStatic)
Relaxed mocksmockk(relaxed = true)Default answers (null/zero), RETURNS_DEEP_STUBS
SpeedCan be slower to initialiseGenerally fast
Ecosystem familiarityVery common in Kotlin Android projectsUniversal in Java and Android

Often better: fakes

Fakes versus mocks A mock is configured per test with stubbed calls and verifies interactions, coupling tests to implementation. A fake is a reusable working implementation with real behaviour, so tests assert outcomes and survive refactoring. Mockstub each call per testverify interactionscouples to implementation Fakeworking in-memory implementationassert outcomes (state)reusable, refactor-friendly
Use fakes for your own interfaces (repositories, data sources), and mocks for interaction checks or awkward third-party types.
FakeArticleRepository.ktKotlin
class FakeArticleRepository : ArticleRepository {
    val articles = MutableStateFlow<List<Article>>(emptyList())
    var failRefresh = false
    override fun observeArticles(): Flow<List<Article>> = articles
    override suspend fun refresh() { if (failRefresh) throw IOException() }
}

When mocks are the right tool

  • Verifying a side effect happened exactly once (analytics event, logger call).
  • Third-party classes that are hard to fake and that you don't wrap.
  • Simulating rare failures in deep collaborators.

Team recommendations

Kotlin-only Android app

MockK for its Kotlin-native API, with fakes for repositories.

Mixed Java/Kotlin codebase

Mockito with mockito-kotlin keeps one library for both languages.

Large test suites

Prefer fakes. Measure mock initialisation cost if tests feel slow.

Common mistakes

  • Mocking data classes and value types. Just create real instances.
  • Relaxed mocks everywhere, which hide missing stubs and let tests pass vacuously.
  • Verifying every call, which breaks tests on harmless refactors.
  • Mocking the class under test.

Frequently asked questions

Can I use both in one project?

You can, but pick one as the standard to keep tests consistent.

Do I need special setup for final classes with Mockito?

Recent Mockito versions use the inline mock maker by default, which supports final classes. Older setups needed explicit configuration.

What about mocking Android framework classes?

Avoid it. Wrap framework calls behind your own interfaces, or use Robolectric when you need real behaviour.

Conclusion

MockK offers the most Kotlin-native API, and Mockito with mockito-kotlin is equally capable for most needs. For your own repositories and data sources, fakes usually produce clearer, more robust tests than either.

Next step: find a different kind of bug in Android Memory Leaks: Causes and Solutions.

Official references

๐Ÿ“ฑ Apps built by Yunok Tech

Real Android apps on Google Play, free to download.

See all our apps โ†’

Ready to build real Android applications?

Kotlin fluency makes everything else in Android easier, from coroutines and Flow to Compose and clean architecture. The fastest way to build that fluency is to write real Kotlin every day and get feedback on it.

Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.

Explore the Android course and take your next step as an Android developer.

Share: LinkedIn X / Twitter WhatsApp