MockK: mi ez, kulcsfogalmak és szintaxis

Szerző: IT Sectr Megjelenés: 2026-04-08 Olvasási idő: 8 perc

A MockK egy Kotlin-first keretrendszer mock-objektumok létrehozására, amelyet kifejezetten a Kotlin ökoszisztémára terveztek, figyelembe véve annak nyelvi jellemzőit: korutinok, extension-függvények, data class és sealed class. Ellentétben a Mockito-val, amelyet Java-ból portoltak Kotlin-ra, a MockK kezdettől fogva Kotlin szintaxisra épült, és nem igényel további bővítményeket a final osztályokkal való munkához. A MockK.io adatai szerint a könyvtárat a Kotlin-projektek több mint 40%ában használják modulteszteléssel.

Főbb pontok

  • MockK — Kotlin-orientált könyvtár mockoláshoz korutinok és nyelvi funkciók támogatásával.
  • mockk() — a mock-objektum létrehozásának fő módszere, hasonló a Mockito.mock()-hoz.
  • every { } — blokk a mock viselkedésének (stubbing) beállítására deklaratív stílusban.
  • coEvery / coVerify — speciális konstrukciók a korutinok suspend-függvényeivel való munkához.
  • Relaxed mock — olyan mock, amely alapértelmezett értékeket ad vissza explicit stubbing nélkül.

Mi az a MockK?

MockK — egy könyvtár mock-objektumok létrehozására, Kotlin nyelven írva és annak szintaxisára optimalizálva. Ugyanazokat a feladatokat oldja meg, mint a Mockito — a tesztelt kód elkülönítése a függőségektől — de ezt Kotlin-specifikus konstrukciók: lambdák, DSL, reified generics és suspend-függvények segítségével teszi.

A MockK fő előnye a portolt megoldásokkal szemben — a Kotlin natív támogatása. A Mockito-ban a final osztályok mockolása opt-in-t igényel (mockito-inline), a statikus módszereke pedig mockStatic-et. A MockK ezt alapértelmezetten támogatja, mivel a Kotlin osztályok alapértelmezetten finalok, és e korlátozás megkerülése be van építve a könyvtár architektúrájába.

Az 1.13.12 verzió (2024) — egy stabil kiadás, amely támogatja a Kotlin 2.0-t, a K2 fordítót és a többplatformos projekteket (KMP). A MockK működik Kotlin/Native és Kotlin/JS környezetben is, ami egyedüli választássá teszi a KMP projektek számára, ahol sem a Mockito, sem az EasyMock nem alkalmazható.

A MockK a Kotlin sajátosságait figyelembe véve lett tervezve, és kihasználja a nyelv képességeit — reified generics, DSL lambdákkal, inline függvények — hogy tömör és típusbiztos API-t nyújtson teljesítményveszteség nélkül.

Hogyan működik a MockK

A MockK mechanizmusa bájtkód-instrumentáción alapul a ByteBuddy könyvtáron keresztül (mint a Mockito), de Kotlin-barát DSL-be csomagolja azt. A when().thenReturn() láncok helyett a MockK every { } és coEvery { } lambda blokkokat használ, amelyek a nyelv természetes kiterjesztésének tűnnek. A motorháztető alatt a MockK elfogja a lambdán belüli hívást, elemzi a módszert és argumentumokat reflekcióval, és összeveti a rögzített stubbing szabályokkal.

MockK alapszintaxis

Az every { mock.method() } returns value blokk úgy értendő, hogy „mindenhányszor, amikor a módszert meghívják, adja vissza az értéket”. Az ilyen deklaratív szintaxis közelebb áll a Kotlin stílushoz, és kiküszöböli az argumentumok sorrendjével kapcsolatos zavart a when()-ben. A Kotlin reified generics-ének köszönhetően a mock típusa automatikusan kikövetkeztethető az osztály explicit megadása nélkül.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: minden findById(1) hívás visszaadja a felhasználót
every { repository.findById(1) } returns User("Alice")

// Hívás és ellenőrzés
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: kevesebb boilerplate

Ellentétben a Mockito-val, ahol minden módszert explicit be kell állítani, a MockK támogatja a relaxed mock-ot — olyan mock-ot, amely „ésszerű” alapértelmezett értékeket ad vissza bármely módszerhez: üres listát a List-hez, 0-t az Int-hez, üres sztringet a String-hez. Ez drasztikusan csökkenti az előkészítő kód mennyiségét.

kotlin
// Relaxed mock — minden módszer alapértelmezett értéket ad vissza
val api = mockk<ApiService>(relaxed = true)

// Nem igényel stubbingot — üres listát ad vissza
println(api.getUsers()) // []

Mockok és relaxált mockok létrehozása

A MockK több módot kínál mock-objektumok létrehozására: mockk<T>() szigorú mock-hoz (minden módszert explicit be kell állítani), mockk<T>(relaxed = true) relaxált mock-hoz és spyk(obj) spy létrehozásához egy valós objektumon.

FüggvényTípusViselkedés stubbing nélkül
mockk()Szigorú mockKivételt dob nem-stubolt módszer hívásakor
mockk(relaxed = true)Relaxált mockAlapértelmezett értéket ad vissza
spyk()SpyValós módszert hív, ha nincs stub beállítva
slot()Argument CaptorElfogja az argumentumot ellenőrzéshez

A választás a szigorú és relaxált mock között a kontextustól függ. A szigorú mock garantálja, hogy a teszt nem használ olyan módszereket, amelyek viselkedése nincs meghatározva — ez növeli a megbízhatóságot. A relaxált mock kényelmes a tesztek gyors prototipizálásához, ahol nem minden függőség számít. A gyakorlatban ajánlott szigorú mock-kal kezdeni, és csak akkor átváltani relaxed-re, ha a stubbing több sort foglal el, mint maga a teszt.

Stubbing: viselkedés beállítása every blokkal

Az every blokk — a stubbing központi konstrukciója a MockK-ban. A lambdán belül egy módszerhívás kerül leírásra konkrét argumentumokkal, majd az érték visszaadása a returns-on, kivétel dobása a throws-on vagy válasz számítása az answers-on keresztül történik.

A stubbing különböző módjai

A MockK támogatja a teszteléshez szükséges összes forgatókönyvet: érték visszaadása, kivétel dobása, válasz számítása argumentumok alapján, több válasz egymás után (hívások sorrendje).

kotlin
// Érték visszaadása
every { repo.findById(1) } returns User("Alice")

// Kivétel dobása
every { repo.findById(999) } throws NotFoundException()

// Dinamikus válasz
every { repo.save(any()) } answers {
    val user = firstArg<User>()
    user.copy(id = 42)
}

// Válaszok sorrendje
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Verify és coVerify korutinokhoz

A Verify a MockK-ban értelemben hasonlít a Mockito.verify()-hez, de Kotlin DSL-t használ: verify { mock.method() }. A suspend-függvényekhez a coVerify { mock.suspendMethod() } használható, amely helyesen működik a korutinokkal, és nem igényel speciális futtatót.

Hívások számának ellenőrzése

A MockK ugyanazokat a módosítókat támogatja, mint a Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). A szintaxis minimalista — a módosító első argumentumként kerül átadásra a verify { } blokkban.

kotlin
// Ellenőrzés: a módszer pontosan 1-szer lett meghívva
verify(exactly = 1) { repo.save(any()) }

// Hívások sorrendjének ellenőrzése
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify suspend-függvényekhez
coVerify { api.fetchUsers() }

Slot: argumentumok elfogása

Az argumentumok ellenőrzéséhez a slot() — az ArgumentCaptor megfelelője — használható. A slot a hívás előtt kerül deklarálásra, átadásra az every vagy verify számára, és a teszt végrehajtása után tartalmazza az elfogott értéket.

kotlin
val userSlot = slot<User>()

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

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

MockK annotációk és JUnit integráció

A MockK @MockK és @RelaxedMockK annotációkat biztosít mockok létrehozásához inicializálással a JUnit 5-ben. A MockKExtension kiterjesztés automatikusan létrehozza a mockokat minden teszt előtt, és utána tisztít — hasonlóan a MockitoExtension-hez, de a relaxed mód támogatásával.

Példa MockKExtensionnel

Az @InjectMockKs annotáció (vagy az alternatív @MockK explicit objektumlétrehozzással) beinjektálja a mockokat a tesztelt példányba. Ez csökkenti a boilerplate-et és tisztábbá teszi a tesztkódot.

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: mit válasszunk Kotlinhoz

A választás a MockK és Mockito között a csapat összetételétől és a projekt típusától függ. A Mockito nagyobb ökoszisztémával, több példával és integrációval rendelkezik, de a MockK tisztább Kotlin szintaxist és natív támogatást nyújt a nyelvi funkciókhoz. Új Kotlin projektekhez a MockK ajánlott idiomatikusabb megoldásként.

SzempontMockKMockito
SzintaxisKotlin DSL (every, verify)Java stílus (when, thenReturn)
KorutinokcoEvery, coVerify (natív)További könyvtárakat igényel
Final classAlapértelmezetten támogatottmockito-inline szükséges
KMPTámogatottNem támogatott
Relaxed mockBeépítettNincs megfelelője
NépszerűségNövekvő a Kotlin közösségbenDominál Java és hibrid projektekben

Tiszta Kotlin projektekhez (Java osztályok nélkül) a MockK előnyösebb: kevesebb boilerplate, natív korutin támogatás, nincs meglepetés a final osztályokkal. Hibrid projektekhez vagy Java háttérrel rendelkező csapatok számára a Mockito továbbra is működő lehetőség marad — mindkét könyvtár használható egy projektben különböző modulokon keresztül. Mockito-ról MockK-ra való áttéréskor elég a @Mock annotációkat @MockK-ra cserélni és a when().thenReturn() blokkokat every { } formátumra átírni.

Gyakran ismételt kérdések

Miben különbözik a relaxed mock a szokásos mock-tól a MockK-ban?

Relaxed mock alapértelmezett értékeket ad vissza az összes nem-stubolt módszerhez (üres lista, 0, null), kivételek dobása nélkül. A szokásos (strict) mock minden módszer explicit stubbingját igényli — különben a teszt megbukik. A relaxed mock gyors tesztekhez kényelmes, a strict — megbízható tesztekhez.

Hogyan lehet mockolni extension-függvényeket a MockK-ban?

MockK támogatja az extension-függvények mockolását a mockkStatic() segítségével. Ez azért lehetséges, mert az extension-függvények Kotlin-ban statikus módszerek, amelyek első paramétere a fogadó. Minden extension-függvényhez meg kell adni azt az osztályt, amelyben deklarálva van.

Működik a MockK Kotlin Multiplatform-mal?

Igen, a MockK támogatja a Kotlin Multiplatform (KMP) közös kódját. A JVM, Native és JS platformokon használható a közös API: mockk(), every, verify. Ez teszi a MockK-ot egyedüli választássá a KMP projektek számára, ahol a Mockito nem működik.

Hogyan ellenőrizhető a hívások sorrendje a MockK-ban?

Használd a verifySequence { }-t — egy blokkot, amelyben a hívások szigorúan a várt sorrendben vannak megadva. Ha a tényleges sorrend eltér, a verifySequence kivételt dob az első nem egyező hívás megjelölésével.

Használható a MockK és a Mockito egy projektben?

Igen, technikailag lehetséges, de nem ajánlott. Konfliktusok léphetnek fel a bájtkód-instrumentáció szintjén (ByteBuddy vs mockito-inline). Ha a projekt már használja a Mockito-t, a MockK-ra való áttérés fokozatosan, modulok elkülönítésével történhet.

Összefoglaló

  • MockK — Kotlin-first könyvtár mockoláshoz natív nyelvi támogatással.
  • every { } — deklaratív DSL a mockok viselkedésének beállításához.
  • coEvery / coVerify — korutin suspend-függvények támogatása további függőségek nélkül.
  • Relaxed mock — mock alapértelmezett értékekkel, ami csökkenti a boilerplate-et.
  • @MockK / @InjectMockKs — annotációk automatikus mock létrehozzáshoz JUnit 5-ben.
  • MockK vs Mockito — MockK előnyösebb tiszta Kotlin és KMP projektekhez.
  • verifySequence — módszerhívások szigorú sorrendjének ellenőrzése.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is