MockK: wat is het, kernconcepten en syntaxis

Auteur: IT Sectr Gepubliceerd: 2026-04-08 Leestijd: 8 min

MockK — is een Kotlin-first framework voor het maken van mock-objecten, speciaal ontworpen voor het Kotlin-ecosysteem met inachtneming van zijn taalkenmerken: coroutines, extensiefuncties, data class en sealed class. In tegenstelling tot Mockito, dat vanuit Java naar Kotlin is gepoort, is MockK vanaf het begin ontworpen voor Kotlin-syntaxis en heeft het geen extra plug-ins nodig om met final-klassen te werken. Volgens gegevens van MockK.io wordt de bibliotheek gebruikt in meer dan 40% van de Kotlin-projecten met modulair testen.

Belangrijkste punten

  • MockK — een Kotlin-gerichte bibliotheek voor mocken met ondersteuning voor coroutines en taalfuncties.
  • mockk() — de belangrijkste methode om een mock-object te maken, vergelijkbaar met Mockito.mock().
  • every { } — blok voor het configureren van mock-gedrag (stubbing) in declaratieve stijl.
  • coEvery / coVerify — speciale constructies voor het werken met suspend-functies van coroutines.
  • Relaxed mock — een mock die standaardwaarden retourneert zonder expliciete stubbing.

Wat is MockK?

MockK — is een bibliotheek voor het maken van mock-objecten, geschreven in Kotlin en geoptimaliseerd voor de syntaxis ervan. Het lost dezelfde taken op als Mockito — isolatie van geteste code van afhankelijkheden — maar doet dit met behulp van Kotlin-specifieke constructies: lambda's, DSL, reified generics en suspend-functies.

Het belangrijkste voordeel van MockK ten opzichte van geporte oplossingen — native ondersteuning voor Kotlin. In Mockito vereist het mocken van een final-klasse opt-in (mockito-inline) en statische methoden vereisen mockStatic. MockK ondersteunt dit standaard, omdat Kotlin-klassen standaard final zijn en het omzeilen van deze beperking is ingebouwd in de architectuur van de bibliotheek.

Versie 1.13.12 (2024) — een stabiele release die Kotlin 2.0, K2-compiler en multiplatform-projecten (KMP) ondersteunt. MockK werkt ook met Kotlin/Native en Kotlin/JS, waardoor het de enige keuze is voor KMP-projecten waar noch Mockito noch EasyMock toepasbaar zijn.

MockK is ontworpen met het oog op de specificiteit van Kotlin en maakt gebruik van taalcapaciteiten — reified generics, DSL met lambda's, inline-functies — om een beknopte en typeveilige API te bieden zonder prestatieverlies.

Hoe werkt MockK

Mechanisme MockK is gebaseerd op bytecode-instrumentatie via de bibliotheek ByteBuddy (net als Mockito), maar verpakt het in een Kotlin-vriendelijke DSL. In plaats van ketens when().thenReturn() gebruikt MockK lambda-blokken every { } en coEvery { }, die eruitzien als een natuurlijke uitbreiding van de taal. Onder de motorkap onderschept MockK de aanroep binnen de lambda, analyseert de methode en argumenten via reflectie en matcht ze met geregistreerde stubbing-regels.

Basis MockK-syntaxis

Het blok every { mock.method() } returns value wordt gelezen als “wanneer de methode wordt aangeroepen, retourneer de waarde”. Een dergelijke declaratieve syntaxis ligt dichter bij de Kotlin-stijl en elimineert verwarring met de volgorde van argumenten in when(). Dankzij reified generics in Kotlin wordt het type mock automatisch afgeleid zonder expliciete klasse-specificatie.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: elke aanroep findById(1) retourneert de gebruiker
every { repository.findById(1) } returns User("Alice")

// Aanroep en verificatie
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: minder boilerplate

In tegenstelling tot Mockito, waar elke methode expliciet moet worden geconfigureerd, ondersteunt MockK relaxed mock — een mock die “redelijke” standaardwaarden retourneert voor elke methode: een lege lijst voor List, 0 voor Int, een lege string voor String. Dit vermindert de hoeveelheid voorbereidende code drastisch.

kotlin
// Relaxed mock — alle methoden retourneren standaardwaarden
val api = mockk<ApiService>(relaxed = true)

// Vereist geen stubbing — retourneert lege lijst
println(api.getUsers()) // []

Maken van mocks en ontspannen mocks

MockK biedt verschillende manieren om mock-objecten te maken: mockk<T>() voor een strikte mock (elke methode moet expliciet worden geconfigureerd), mockk<T>(relaxed = true) voor een ontspannen mock en spyk(obj) voor het maken van een spy op een echt object.

FunctieTypeGedrag zonder stubbing
mockk()Strikte mockGooit uitzondering bij aanroep van niet-gestubde methode
mockk(relaxed = true)Ontspannen mockRetourneert standaardwaarde
spyk()SpyRoept echte methode aan als stub niet is geconfigureerd
slot()Argument CaptorVangt argument voor verificatie

De keuze tussen een strikte en ontspannen mock hangt af van de context. Een strikte mock garandeert dat de test geen methoden gebruikt waarvan het gedrag niet is gedefinieerd — dit verhoogt de betrouwbaarheid. Een ontspannen mock is handig voor snel prototypen van tests waar niet alle afhankelijkheden belangrijk zijn. In de praktijk wordt aanbevolen om met een strikte mock te beginnen en alleen over te schakelen naar relaxed wanneer stubbing meer regels inneemt dan de test zelf.

Stubbing: gedrag configureren met every-blok

Het every-blok — is de centrale constructie van stubbing in MockK. Binnen de lambda wordt een methodeaanroep met specifieke argumenten beschreven, waarna de waarde wordt geretourneerd via returns, een uitzondering wordt gegooid via throws of een antwoord wordt berekend via answers.

Verschillende manieren van stubbing

MockK ondersteunt alle scenario's die nodig zijn voor testen: waarde retourneren, uitzondering gooien, antwoord berekenen op basis van argumenten, meerdere antwoorden op volgorde (sequentie van aanroepen).

kotlin
// Waarde retourneren
every { repo.findById(1) } returns User("Alice")

// Uitzondering gooien
every { repo.findById(999) } throws NotFoundException()

// Dynamisch antwoord
every { repo.save(any()) } answers {
    val user = firstArg<User>()
    user.copy(id = 42)
}

// Antwoordsequentie
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Verify en coVerify voor coroutines

Verify in MockK is qua betekenis analoog aan Mockito.verify() maar gebruikt Kotlin DSL: verify { mock.method() }. Voor suspend-functies wordt coVerify { mock.suspendMethod() } gebruikt, dat correct werkt met coroutines en geen speciale runner vereist.

Aantal aanroepen controleren

MockK ondersteunt dezelfde modificatoren als Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). De syntaxis is minimalistisch — de modificator wordt als eerste argument in verify { } doorgegeven.

kotlin
// Verificatie: methode precies 1 keer aangeroepen
verify(exactly = 1) { repo.save(any()) }

// Volgorde van aanroepen controleren
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify voor suspend-functies
coVerify { api.fetchUsers() }

Slot: argumenten vastleggen

Voor het controleren van argumenten wordt slot() gebruikt — de analogie van ArgumentCaptor. De slot wordt vlak voor de aanroep gedeclareerd, doorgegeven aan every of verify, en bevat na uitvoering van de test de vastgelegde waarde.

kotlin
val userSlot = slot<User>()

verify { repo.save(capture(userSlot)) }

assertEquals("Alice", userSlot.captured.name)

MockK-annotaties en JUnit-integratie

MockK biedt annotaties @MockK en @RelaxedMockK voor het maken van mocks via initialisatie in JUnit 5. De extensie MockKExtension maakt automatisch mocks aan voor elke test en ruimt daarna op — vergelijkbaar met MockitoExtension, maar met ondersteuning voor de relaxed-modus.

Voorbeeld met MockKExtension

De annotatie @InjectMockKs (of het alternatief @MockK met expliciete objectcreatie) injecteert mocks in de geteste instantie. Dit vermindert boilerplate en maakt de testcode schoner.

kotlin
@ExtendWith(MockKExtension::class)
class UserServiceTest {

    @MockK
    lateinit var repository: UserRepository

    @InjectMockKs
    lateinit var service: UserService

    @Test
    fun `getUser returns user from repository`() {
        every { repository.findById(1) } returns User("Alice")
        assertEquals("Alice", service.getUser(1)?.name)
    }
}

MockK vs Mockito: wat te kiezen voor Kotlin

De keuze tussen MockK en Mockito hangt af van de teamsamenstelling en het projecttype. Mockito heeft een groter ecosysteem, meer voorbeelden en integraties, maar MockK biedt een schonere Kotlin-syntaxis en native ondersteuning voor taalfuncties. Voor nieuwe Kotlin-projecten wordt MockK aanbevolen als de meer idiomatische oplossing.

CriteriumMockKMockito
SyntaxisKotlin DSL (every, verify)Java-stijl (when, thenReturn)
CoroutinescoEvery, coVerify (natively)Vereist extra bibliotheken
Final classStandaard ondersteundVereist mockito-inline
KMPOndersteundNiet ondersteund
Relaxed mockIngebouwdGeen equivalent
PopulariteitGroeiend in Kotlin-gemeenschapDomineert in Java en hybride projecten

Voor projecten in puur Kotlin (zonder Java-klassen) verdient MockK de voorkeur: minder boilerplate, native ondersteuning voor coroutines, geen verrassingen met final-klassen. Voor hybride projecten of teams met Java-achtergrond blijft Mockito een werkende optie — beide bibliotheken kunnen in hetzelfde project via verschillende modules worden gebruikt. Bij migratie van Mockito naar MockK volstaat het om @Mock-annotaties te vervangen door @MockK en when().thenReturn()-blokken te herschrijven naar every { }-formaat.

Veelgestelde vragen

Wat is het verschil tussen relaxed mock en gewone mock in MockK?

Relaxed mock retourneert standaardwaarden voor alle niet-gestubde methoden (lege lijst, 0, null) zonder uitzonderingen te gooien. Een gewone (strict) mock vereist expliciete stubbing van elke methode — anders faalt de test. Relaxed mock is handig voor snelle tests, strict — voor betrouwbare tests.

Hoe mock je extensiefuncties in MockK?

MockK ondersteunt het mocken van extensiefuncties via mockkStatic(). Dit is mogelijk omdat extensiefuncties in Kotlin statische methoden zijn met een eerste receptorparameter. Voor elke extensiefunctie moet de klasse worden opgegeven waarin deze is gedeclareerd.

Werkt MockK met Kotlin Multiplatform?

Ja, MockK ondersteunt Kotlin Multiplatform (KMP) voor gemeenschappelijke code. Op de platforms JVM, Native en JS kan de gemeenschappelijke API mockk(), every, verify worden gebruikt. Dit maakt MockK de enige keuze voor KMP-projecten waar Mockito niet werkt.

Hoe controleer je de volgorde van aanroepen in MockK?

Gebruik verifySequence { } — een blok waarin aanroepen strikt in de verwachte volgorde worden gespecificeerd. Als de werkelijke volgorde afwijkt, gooit verifySequence een uitzondering met vermelding van de eerste niet-overeenkomende aanroep.

Kun je MockK en Mockito in hetzelfde project gebruiken?

Ja, technisch is het mogelijk, maar niet aanbevolen. Conflicten kunnen optreden op het niveau van bytecode-instrumentatie (ByteBuddy vs mockito-inline). Als het project al Mockito gebruikt, kan de migratie naar MockK geleidelijk verlopen via isolatie van modules.

Samenvatting

  • MockK — Kotlin-first bibliotheek voor mocken met native taalondersteuning.
  • every { } — declaratieve DSL voor het configureren van mock-gedrag.
  • coEvery / coVerify — ondersteuning voor coroutine suspend-functies zonder extra afhankelijkheden.
  • Relaxed mock — mock met standaardwaarden die boilerplate vermindert.
  • @MockK / @InjectMockKs — annotaties voor automatisch maken van mocks in JUnit 5.
  • MockK vs Mockito — MockK heeft de voorkeur voor pure Kotlin-projecten en KMP.
  • verifySequence — controle van strikte volgorde van methodeaanroepen.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook