MockK: шта је то, кључни појмови и синтакса

Аутор: IT Sectr Објављено: 2026-04-08 Време читања: 8 мин

MockK — је Kotlin-first оквир за креирање мок објеката, дизајниран специјално за екосистем Kotlin узимајући у обзир његове језичке карактеристике: корутине, екстензионе функције, data class и sealed class. За разлику од Mockito-а, који је портован на Kotlin из Java-е, MockK је од почетка пројектован за Kotlin синтаксу и не захтева додатне додатке за рад са final класама. Према подацима MockK.io, библиотека се користи у више од 40% Kotlin пројеката са модуларним тестирањем.

Главно

  • MockK — Kotlin-оријентисана библиотека за моковање са подршком за корутине и језичке функције.
  • mockk() — основни метод креирања мок објекта, аналоган Mockito.mock().
  • every { } — блок за подешавање понашања мока (stubbing) у декларативном стилу.
  • coEvery / coVerify — специјалне конструкције за рад са suspend-функцијама корутина.
  • Relaxed mock — мок који враћа подразумеване вредности без експлицитног стаббинга.

Шта је MockK?

MockK — је библиотека за креирање мок објеката, написана на Kotlin-у и оптимизована за његову синтаксу. Решава исте задатке као Mockito — изолација тестираног кода од зависности — али то чини користећи Kotlin-специфичне конструкције: ламбде, DSL, reified generics и suspend-функције.

Главна предност MockK-а у односу на портована решења — нативна подршка за Kotlin. У Mockito-у, моковање final класе захтева opt-in (mockito-inline), а статичких метода — mockStatic. MockK ово подржава подразумевано, јер су Kotlin класе подразумевано final, а заобилажење овог ограничења је уграђено у архитектуру библиотеке.

Верзија 1.13.12 (2024) — стабилно издање које подржава Kotlin 2.0, K2 компајлер и мулти-платформске пројекте (KMP). MockK такође ради са Kotlin/Native и Kotlin/JS, што га чини јединим избором за KMP пројекте где ни Mockito ни EasyMock нису применљиви.

MockK је пројектован узимајући у обзир специфику Kotlin-а и користи језичке могућности — reified generics, DSL са ламбдама, inline функције — да би обезбедио концизан и типно-безбедан API без губитка перформанси.

Како ради MockK

Механизам MockK-а се заснива на бајткод-инструментацији кроз библиотеку ByteBuddy (као и Mockito), али је облачи у Kotlin-пријатељски DSL. Уместо ланаца when().thenReturn(), MockK користи ламбда блокове every { } и coEvery { }, који изгледају као природно проширење језика. Испод хаубе, MockK пресреће позив унутар ламбде, анализира метод и аргументе кроз рефлексију и упарује их са забележеним правилима стаббинга.

Основна синтакса MockK-а

Блок every { mock.method() } returns value чита се као „сваки пут када се метод позове, врати вредност”. Оваква декларативна синтакса је ближа Kotlin стилу и елиминише забуну са редоследом аргумената у when(). Захваљујући reified generics у Kotlin-у, тип мока се изводи аутоматски без експлицитног навођења класе.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: сваки позив findById(1) враћа корисника
every { repository.findById(1) } returns User("Alice")

// Позив и провера
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: мање boilerplate-а

За разлику од Mockito-а, где сваки метод мора бити експлицитно подешен, MockK подржава relaxed mock — мок који враћа „разумне” подразумеване вредности за било који метод: празну листу за List, 0 за Int, празан стринг за String. Ово драстично смањује количину припремног кода.

kotlin
// Relaxed mock — сви методи враћају подразумеване вредности
val api = mockk<ApiService>(relaxed = true)

// Не захтева стаббинг — вратиће празну листу
println(api.getUsers()) // []

Креирање мокова и релаксираних мокова

MockK нуди неколико начина за креирање мок објеката: mockk<T>() за строги мок (сваки метод мора бити експлицитно подешен), mockk<T>(relaxed = true) за релаксирани мок и spyk(obj) за креирање шпијуна на реалном објекту.

ФункцијаТипПонашање без стаббинга
mockk()Строги мокБаца изузетак при позиву не-стабованог метода
mockk(relaxed = true)Релаксирани мокВраћа подразумевану вредност
spyk()ШпијунПозива реални метод ако стаб није подешен
slot()Argument CaptorХвата аргумент за проверу

Избор између строгог и релаксираног мока зависи од контекста. Строги мок гарантује да тест не користи методе чије понашање није дефинисано — ово повећава поузданост. Релаксирани мок је згодан за брзо прототипирање тестова где нису све зависности важне. У пракси, препоручује се почети са строгим моком и прећи на relaxed само када стаббинг заузима више линија од самог теста.

Stubbing: подешавање понашања са every блоком

Every блок — централна конструкција стаббинга у MockK-у. Унутар ламбде се описује позив метода са конкретним аргументима, а затим се враћа вредност кроз returns, баца изузетак кроз throws или израчунава одговор кроз answers.

Различити начини стаббинга

MockK подржава све сценарије потребне за тестирање: враћање вредности, бацање изузетка, израчунавање одговора на основу аргумената, више одговора по реду (секвенца позива).

kotlin
// Враћање вредности
every { repo.findById(1) } returns User("Alice")

// Бацање изузетка
every { repo.findById(999) } throws NotFoundException()

// Динамички одговор
every { repo.save(any()) } answers {
    val user = firstArg<User>()
    user.copy(id = 42)
}

// Секвенца одговора
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Verify и coVerify за корутине

Verify у MockK-у је аналоган Mockito.verify() по значењу, али користи Kotlin DSL: verify { mock.method() }. За suspend-функције користи се coVerify { mock.suspendMethod() }, који коректно ради са корутинама и не захтева специјални раннер.

Провера броја позива

MockK подржава исте модификаторе као Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). Синтакса је минималистичка — модификатор се прослеђује као први аргумент у verify { }.

kotlin
// Провера: метод позван тачно 1 пут
verify(exactly = 1) { repo.save(any()) }

// Провера редоследа позива
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify за suspend-функције
coVerify { api.fetchUsers() }

Slot: хватање аргумената

За проверу аргумената користи се slot() — аналог ArgumentCaptor-а. Slot се декларише пре позива, прослеђује у every или verify, и након извршења теста садржи ухваћену вредност.

kotlin
val userSlot = slot<User>()

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

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

Анотације MockK и JUnit интеграција

MockK пружа анотације @MockK и @RelaxedMockK за креирање мокова кроз иницијализацију у JUnit 5. Екстензија MockKExtension аутоматски креира мокове пре сваког теста и чисти после — аналогно MockitoExtension-у, али са подршком за relaxed режим.

Пример са MockKExtension

Анотација @InjectMockKs (или алтернатива @MockK са експлицитним креирањем објекта) убризгава мокове у тестирани инстанцу. Ово смањује boilerplate и чини код теста чистијим.

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: шта изабрати за Kotlin

Избор између MockK-а и Mockito-а зависи од састава тима и типа пројекта. Mockito има већи екосистем, више примера и интеграција, али MockK пружа чистију Kotlin синтаксу и нативну подршку за језичке функције. За нове Kotlin пројекте, MockK се препоручује као идиоматичније решење.

КритеријумMockKMockito
СинтаксаKotlin DSL (every, verify)Java стил (when, thenReturn)
КорутинеcoEvery, coVerify (нативно)Захтева додатне библиотеке
Final classПодржано подразумеваноЗахтева mockito-inline
KMPПодржаноНије подржано
Relaxed mockУграђенНема аналога
ПопуларностРастућа у Kotlin заједнициДоминира у Java и хибридним пројектима

За пројекте на чистом Kotlin-у (без Java класа) MockK је пожељнији: мање boilerplate-а, нативна подршка за корутине, без изненађења са final класама. За хибридне пројекте или тимове са Java позадином, Mockito остаје радна опција — обе библиотеке се могу користити у истом пројекту кроз различите модуле. При миграцији са Mockito-а на MockK, довољно је заменити анотације @Mock са @MockK и преписати блокове when().thenReturn() у формат every { }.

Често постављана питања

Чим се relaxed mock разликује од обичног мока у MockK-у?

Relaxed mock враћа подразумеване вредности за све не-стабоване методе (празна листа, 0, null), без бацања изузетака. Обичан (strict) mock захтева експлицитан стаббинг сваке методе — иначе тест пада. Relaxed mock је згодан за брзе тестове, strict — за поуздане.

Како моковати екстензионе функције у MockK-у?

MockK подржава моковање екстензионих функција кроз mockkStatic(). Ово је могуће јер су екстензионе функције у Kotlin-у статички методи са првим параметром-примаоцем. За сваку екстензиону функцију потребно је навести класу у којој је декларисана.

Да ли MockK ради са Kotlin Multiplatform?

Да, MockK подржава Kotlin Multiplatform (KMP) за заједнички код. На платформама JVM, Native и JS може се користити заједнички API mockk(), every, verify. Ово чини MockK јединим избором за KMP пројекте где Mockito не ради.

Како проверити редослед позива у MockK-у?

Користи verifySequence { } — блок у коме се позиви наводе строго у очекиваном редоследу. Ако се стварни редослед разликује, verifySequence ће бацити изузетак са назнаком првог неусаглашеног позива.

Могу ли се користити MockK и Mockito у истом пројекту?

Да, технички је могуће, али се не препоручује. Конфликти могу настати на нивоу бајткод-инструментације (ByteBuddy vs mockito-inline). Ако пројекат већ користи Mockito, миграција на MockK може бити постепена кроз изолацију модула.

Закључак

  • MockK — Kotlin-first библиотека за моковање са нативном подршком језика.
  • every { } — декларативни DSL за подешавање понашања мокова.
  • coEvery / coVerify — подршка за suspend-функције корутина без додатних зависности.
  • Relaxed mock — мок са подразумеваним вредностима, смањује boilerplate.
  • @MockK / @InjectMockKs — анотације за аутоматско креирање мокова у JUnit 5.
  • MockK vs Mockito — MockK је пожељнији за чисте Kotlin пројекте и KMP.
  • verifySequence — провера строгог редоследа позива метода.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође