MockK: cos'è, concetti chiave e sintassi

Autore: IT Sectr Pubblicato: 2026-04-08 Tempo di lettura: 8 min

MockK è un framework Kotlin-first per creare oggetti mock, progettato specificamente per l'ecosistema Kotlin tenendo conto delle sue caratteristiche linguistiche: coroutine, funzioni di estensione, data class e sealed class. A differenza di Mockito, che è stato portato su Kotlin da Java, MockK è stato progettato fin dall'inizio per la sintassi Kotlin e non richiede plugin aggiuntivi per funzionare con le classi final. Secondo MockK.io, la libreria è utilizzata in più del 40% dei progetti Kotlin con test unitari.

Punti chiave

  • MockK — una libreria di mocking orientata a Kotlin con supporto per coroutine e funzionalità del linguaggio.
  • mockk() — il metodo principale per creare un oggetto mock, simile a Mockito.mock().
  • every { } — un blocco per configurare il comportamento del mock (stubbing) in stile dichiarativo.
  • coEvery / coVerify — costrutti speciali per lavorare con le funzioni suspend delle coroutine.
  • Relaxed mock — un mock che restituisce valori predefiniti senza stubbing esplicito.

Cos'è MockK?

MockK è una libreria per creare oggetti mock, scritta in Kotlin e ottimizzata per la sua sintassi. Risolve gli stessi problemi di Mockito — isolare il codice testato dalle dipendenze — ma lo fa utilizzando costrutti specifici di Kotlin: lambda, DSL, reified generics e funzioni suspend.

Il principale vantaggio di MockK rispetto alle soluzioni portate è il supporto nativo per Kotlin. In Mockito, simulare una classe final richiede opt-in (mockito-inline) e i metodi statici richiedono mockStatic. MockK lo supporta per impostazione predefinita, poiché le classi Kotlin sono final per impostazione predefinita e aggirare questa limitazione è integrato nell'architettura della libreria.

La versione 1.13.12 (2024) è una versione stabile che supporta Kotlin 2.0, il compilatore K2 e i progetti multipiattaforma (KMP). MockK funziona anche con Kotlin/Native e Kotlin/JS, rendendolo l'unica scelta per i progetti KMP dove né Mockito né EasyMock sono applicabili.

MockK è progettato tenendo conto delle specificità di Kotlin e utilizza le funzionalità del linguaggio — reified generics, DSL con lambda, funzioni inline — per fornire un'API concisa e type-safe senza sacrificare le prestazioni.

Come funziona MockK

Il meccanismo di MockK si basa sull'instrumentazione del bytecode tramite la libreria ByteBuddy (come Mockito), ma la avvolge in un DSL amichevole per Kotlin. Invece di catene when().thenReturn(), MockK utilizza blocchi lambda every { } e coEvery { } che sembrano un'estensione naturale del linguaggio. Sotto il cofano, MockK intercetta la chiamata all'interno del lambda, analizza il metodo e gli argomenti tramite riflessione e li confronta con le regole di stubbing registrate.

Sintassi di base di MockK

Il blocco every { mock.method() } returns value si legge come “ogni volta che il metodo viene chiamato, restituisci il valore.” Questa sintassi dichiarativa è più vicina allo stile Kotlin ed elimina la confusione sull'ordine degli argomenti in when(). Grazie ai reified generics di Kotlin, il tipo del mock viene dedotto automaticamente senza specificare esplicitamente la classe.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: ogni chiamata a findById(1) restituisce l'utente
every { repository.findById(1) } returns User("Alice")

// Chiamata e verifica
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: meno codice boilerplate

A differenza di Mockito, dove ogni metodo deve essere configurato esplicitamente, MockK supporta il relaxed mock — un mock che restituisce valori predefiniti “ragionevoli” per qualsiasi metodo: una lista vuota per List, 0 per Int, una stringa vuota per String. Questo riduce drasticamente la quantità di codice di configurazione.

kotlin
// Relaxed mock — tutti i metodi restituiscono valori predefiniti
val api = mockk<ApiService>(relaxed = true)

// Non richiede stubbing — restituisce una lista vuota
println(api.getUsers()) // []

Creazione di mock e mock rilassati

MockK offre diversi modi per creare oggetti mock: mockk<T>() per mock rigorosi (ogni metodo deve essere configurato esplicitamente), mockk<T>(relaxed = true) per mock rilassati e spyk(obj) per creare una spia su un oggetto reale.

FunzioneTipoComportamento senza stubbing
mockk()Mock rigorosoLancia un'eccezione quando viene chiamato un metodo non configurato
mockk(relaxed = true)Mock rilassatoRestituisce il valore predefinito
spyk()SpiaChiama il metodo reale se nessuno stub è configurato
slot()Argument CaptorCattura l'argomento per la verifica

La scelta tra mock rigoroso e rilassato dipende dal contesto. Un mock rigoroso garantisce che il test non utilizzi metodi il cui comportamento non è definito — questo aumenta l'affidabilità. Un mock rilassato è conveniente per il prototipazione rapida di test dove non tutte le dipendenze sono importanti. In pratica, si consiglia di iniziare con un mock rigoroso e passare a rilassato solo quando lo stubbing occupa più righe del test stesso.

Stubbing: configurazione del comportamento con il blocco every

Il blocco every è il costrutto centrale di stubbing in MockK. All'interno del lambda, viene descritta una chiamata a un metodo con argomenti specifici, quindi un valore viene restituito tramite returns, un'eccezione viene lanciata tramite throws o una risposta viene calcolata tramite answers.

Diversi modi di stubbing

MockK supporta tutti gli scenari necessari per i test: restituire un valore, lanciare un'eccezione, calcolare una risposta basata sugli argomenti e risposte multiple in ordine (sequenza di chiamate).

kotlin
// Restituire valore
every { repo.findById(1) } returns User("Alice")

// Lanciare eccezione
every { repo.findById(999) } throws NotFoundException()

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

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

Verify e coVerify per le coroutine

Verify in MockK è simile a Mockito.verify() nello scopo, ma utilizza il DSL Kotlin: verify { mock.method() }. Per le funzioni suspend, si utilizza coVerify { mock.suspendMethod() }, che funziona correttamente con le coroutine e non richiede un runner speciale.

Verifica del numero di chiamate

MockK supporta gli stessi modificatori di Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). La sintassi è minimalista — il modificatore viene passato come primo argomento in verify { }.

kotlin
// Verifica: metodo chiamato esattamente 1 volta
verify(exactly = 1) { repo.save(any()) }

// Verificare ordine chiamate
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify per funzioni suspend
coVerify { api.fetchUsers() }

Slot: cattura degli argomenti

Per la verifica degli argomenti si utilizza slot() — un analogo di ArgumentCaptor. Uno slot viene dichiarato prima della chiamata, passato a every o verify, e dopo l'esecuzione del test contiene il valore catturato.

kotlin
val userSlot = slot<User>()

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

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

Annotazioni MockK e integrazione JUnit

MockK fornisce le annotazioni @MockK e @RelaxedMockK per creare mock tramite inizializzazione in JUnit 5. L'estensione MockKExtension crea automaticamente mock prima di ogni test e pulisce dopo — simile a MockitoExtension, ma con supporto per la modalità rilassata.

Esempio con MockKExtension

L'annotazione @InjectMockKs (o l'alternativa @MockK con creazione esplicita dell'oggetto) inietta i mock nell'istanza testata. Questo riduce il boilerplate e rende il codice del test più pulito.

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: cosa scegliere per Kotlin

La scelta tra MockK e Mockito dipende dalla composizione del team e dal tipo di progetto. Mockito ha un ecosistema più ampio, più esempi e più integrazioni, ma MockK offre una sintassi Kotlin più pulita e un supporto nativo per le funzionalità del linguaggio. Per i nuovi progetti Kotlin, MockK è raccomandato come soluzione più idiomatica.

CriterioMockKMockito
SintassiDSL Kotlin (every, verify)Stile Java (when, thenReturn)
CoroutinecoEvery, coVerify (nativo)Richiede librerie aggiuntive
Classe finalSupportato per impostazione predefinitaRichiede mockito-inline
KMPSupportatoNon supportato
Relaxed mockIntegratoNessun equivalente
PopolaritàCrescente nella community KotlinDomina nei progetti Java e ibridi

Per i progetti in Kotlin puro (senza classi Java), MockK è preferibile: meno boilerplate, supporto nativo per le coroutine, nessuna sorpresa con le classi final. Per i progetti ibridi o i team con esperienza Java, Mockito rimane un'opzione funzionante — entrambe le librerie possono essere utilizzate nello stesso progetto attraverso moduli diversi. Durante la migrazione da Mockito a MockK, è sufficiente sostituire le annotazioni @Mock con @MockK e riscrivere i blocchi when().thenReturn() nel formato every { }.

Domande frequenti

In che modo un relaxed mock differisce da un mock normale in MockK?

Relaxed mock restituisce valori predefiniti per tutti i metodi non configurati (lista vuota, 0, null) senza lanciare eccezioni. Un mock normale (rigoroso) richiede lo stubbing esplicito di ogni metodo — altrimenti il test fallisce. Il relaxed mock è conveniente per test rapidi, il rigoroso per test affidabili.

Come simulare le funzioni di estensione in MockK?

MockK supporta la simulazione di funzioni di estensione tramite mockkStatic(). Questo è possibile perché le funzioni di estensione in Kotlin sono metodi statici con il ricevitore come primo parametro. Per ogni funzione di estensione, è necessario specificare la classe in cui è dichiarata.

MockK funziona con Kotlin Multiplatform?

Sì, MockK supporta Kotlin Multiplatform (KMP) per il codice comune. Sulle piattaforme JVM, Native e JS, è possibile utilizzare l'API comune: mockk(), every, verify. Questo rende MockK l'unica scelta per i progetti KMP dove Mockito non funziona.

Come verificare l'ordine delle chiamate in MockK?

Utilizza verifySequence { } — un blocco in cui le chiamate sono specificate rigorosamente nell'ordine previsto. Se l'ordine effettivo differisce, verifySequence lancerà un'eccezione indicando la prima chiamata non corrispondente.

Si possono usare MockK e Mockito nello stesso progetto?

Sì, tecnicamente è possibile, ma non raccomandato. Possono verificarsi conflitti a livello di instrumentazione del bytecode (ByteBuddy vs mockito-inline). Se un progetto utilizza già Mockito, la migrazione a MockK può essere graduale attraverso l'isolamento dei moduli.

Riepilogo

  • MockK — una libreria di mocking Kotlin-first con supporto nativo del linguaggio.
  • every { } — un DSL dichiarativo per configurare il comportamento dei mock.
  • coEvery / coVerify — supporto per le funzioni suspend nelle coroutine senza dipendenze aggiuntive.
  • Relaxed mock — un mock con valori predefiniti che riduce il boilerplate.
  • @MockK / @InjectMockKs — annotazioni per la creazione automatica di mock in JUnit 5.
  • MockK vs Mockito — MockK è preferibile per progetti Kotlin puri e KMP.
  • verifySequence — verifica dell'ordine rigoroso delle chiamate ai metodi.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche