MockK: ano ito, mga pangunahing konsepto at syntax

May-akda: IT Sectr Nai-publish: 2026-04-08 Oras ng pagbabasa: 8 min

MockK — ay isang Kotlin-first framework para sa paggawa ng mga mock-object, na espesyal na idinisenyo para sa Kotlin ecosystem na isinasaalang-alang ang mga feature ng wika nito: mga coroutine, extension-function, data class at sealed class. Hindi tulad ng Mockito, na na-port sa Kotlin mula sa Java, ang MockK ay orihinal na idinisenyo para sa Kotlin syntax at hindi nangangailangan ng mga karagdagang plugin para sa pagtatrabaho sa mga final-class. Ayon sa datos ng MockK.io, ang library ay ginagamit sa higit sa 40% ng mga Kotlin project na may unit testing.

Mga Pangunahing Punto

  • MockK — isang Kotlin-oriented library para sa mocking na may suporta para sa mga coroutine at feature ng wika.
  • mockk() — pangunahing paraan ng paggawa ng mock-object, kahalintulad ng Mockito.mock().
  • every { } — bloke para sa pag-configure ng pag-uugali ng mock (stubbing) sa deklaratibong estilo.
  • coEvery / coVerify — mga espesyal na konstruksyon para sa pagtatrabaho sa mga suspend-function ng coroutine.
  • Relaxed mock — isang mock na nagbabalik ng mga default na halaga nang walang hayagang stubbing.

Ano ang MockK?

MockK — ay isang library para sa paggawa ng mga mock-object, na nakasulat sa Kotlin at na-optimize para sa syntax nito. Nilulutas nito ang parehong mga gawain tulad ng Mockito — paghihiwalay ng nasubok na code mula sa mga dependency — ngunit ginagawa ito gamit ang mga konstruksyong tiyak sa Kotlin: mga lambda, DSL, reified generics at mga suspend-function.

Ang pangunahing bentahe ng MockK kumpara sa mga naka-port na solusyon — native na suporta para sa Kotlin. Sa Mockito, ang pag-mock ng final-class ay nangangailangan ng opt-in (mockito-inline), at ng mga static na pamamaraan — mockStatic. Sinusuportahan ito ng MockK bilang default, dahil ang mga Kotlin class ay default na final, at ang pag-ikot sa limitasyong ito ay naka-embed sa arkitektura ng library.

Bersyon 1.13.12 (2024) — isang stable na release na sumusuporta sa Kotlin 2.0, K2 compiler at mga multi-platform na proyekto (KMP). Gumagana rin ang MockK sa Kotlin/Native at Kotlin/JS, na ginagawa itong nag-iisang pagpipilian para sa mga proyektong KMP kung saan hindi naaangkop ang Mockito o EasyMock.

Ang MockK ay idinisenyo na isinasaalang-alang ang mga detalye ng Kotlin at gumagamit ng mga kakayahan ng wika — reified generics, DSL na may mga lambda, inline-function — upang magbigay ng isang maigsi at type-safe na API nang walang pagkawala ng pagganap.

Paano gumagana ang MockK

Mekanismo Ang MockK ay batay sa bytecode instrumentation sa pamamagitan ng library na ByteBuddy (tulad ng Mockito), ngunit binabalot ito sa isang Kotlin-friendly na DSL. Sa halip na mga chain ng when().thenReturn(), gumagamit ang MockK ng mga lambda block na every { } at coEvery { }, na mukhang natural na extension ng wika. Sa ilalim ng hood, naharang ng MockK ang tawag sa loob ng lambda, sinusuri ang pamamaraan at mga argumento sa pamamagitan ng reflection at itinutugma ang mga ito sa naitala na mga panuntunan ng stubbing.

Pangunahing syntax ng MockK

Ang block na every { mock.method() } returns value ay binabasa bilang “sa tuwing tatawagin ang pamamaraan, ibalik ang halaga”. Ang ganitong deklaratibong syntax ay mas malapit sa estilo ng Kotlin at inaalis ang pagkalito sa pagkakasunud-sunod ng mga argumento sa when(). Dahil sa reified generics ng Kotlin, ang uri ng mock ay awtomatikong nahihinuha nang walang hayagang pagtukoy ng klase.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: bawat tawag findById(1) ay nagbabalik ng user
every { repository.findById(1) } returns User("Alice")

// Tawag at pagpapatunay
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: mas kaunting boilerplate

Hindi tulad ng Mockito, kung saan ang bawat pamamaraan ay kailangang i-configure nang hayagan, sinusuportahan ng MockK ang relaxed mock — isang mock na nagbabalik ng “makatwirang” default na mga halaga para sa anumang pamamaraan: walang laman na listahan para sa List, 0 para sa Int, walang laman na string para sa String. Ito ay lubhang nagbabawas ng dami ng paghahandang code.

kotlin
// Relaxed mock — lahat ng pamamaraan ay nagbabalik ng default na halaga
val api = mockk<ApiService>(relaxed = true)

// Hindi nangangailangan ng stubbing — magbabalik ng walang laman na listahan
println(api.getUsers()) // []

Paggawa ng mga mock at relaxed na mock

MockK ay nag-aalok ng ilang paraan upang lumikha ng mga mock-object: mockk<T>() para sa isang mahigpit na mock (bawat pamamaraan ay dapat na hayagang i-configure), mockk<T>(relaxed = true) para sa isang relaxed na mock at spyk(obj) para sa paggawa ng isang spy sa isang tunay na bagay.

FunctionUriPag-uugali nang walang stubbing
mockk()Mahigpit na mockNagtatapon ng exception sa pagtawag ng hindi naka-stub na pamamaraan
mockk(relaxed = true)Relaxed na mockNagbabalik ng default na halaga
spyk()SpyTumatawag ng tunay na pamamaraan kung hindi naka-configure ang stub
slot()Argument CaptorKumukuha ng argumento para sa pagpapatunay

Ang pagpili sa pagitan ng mahigpit at relaxed na mock ay depende sa konteksto. Tinitiyak ng mahigpit na mock na ang test ay hindi gumagamit ng mga pamamaraan na ang pag-uugali ay hindi tinukoy — pinapataas nito ang pagiging maaasahan. Ang relaxed na mock ay maginhawa para sa mabilis na prototyping ng mga test kung saan hindi lahat ng dependency ay mahalaga. Sa pagsasagawa, inirerekumenda na magsimula sa isang mahigpit na mock at lumipat sa relaxed lamang kapag ang stubbing ay sumasakop ng mas maraming linya kaysa sa test mismo.

Stubbing: pag-configure ng pag-uugali gamit ang every block

Ang every block — ay ang sentral na konstruksyon ng stubbing sa MockK. Sa loob ng lambda, inilalarawan ang isang tawag sa pamamaraan na may mga tiyak na argumento, at pagkatapos ay ibinabalik ang halaga sa pamamagitan ng returns, itinatapon ang exception sa pamamagitan ng throws o kinakalkula ang sagot sa pamamagitan ng answers.

Iba't ibang paraan ng stubbing

Sinusuportahan ng MockK ang lahat ng mga sitwasyong kinakailangan para sa pagsubok: pagbabalik ng halaga, pagtatapon ng exception, pagkalkula ng sagot batay sa mga argumento, maraming sagot sa pagkakasunud-sunod (pagkakasunod-sunod ng mga tawag).

kotlin
// Pagbabalik ng halaga
every { repo.findById(1) } returns User("Alice")

// Pagtatapon ng exception
every { repo.findById(999) } throws NotFoundException()

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

// Pagkakasunod-sunod ng mga sagot
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Verify at coVerify para sa mga coroutine

Verify sa MockK ay kahalintulad sa Mockito.verify() sa kahulugan ngunit gumagamit ng Kotlin DSL: verify { mock.method() }. Para sa mga suspend-function, ginagamit ang coVerify { mock.suspendMethod() }, na gumagana nang tama sa mga coroutine at hindi nangangailangan ng espesyal na runner.

Pagsusuri ng bilang ng mga tawag

Sinusuportahan ng MockK ang parehong mga modifier tulad ng Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). Minimalist ang syntax — ang modifier ay ipinapasa bilang unang argumento sa verify { }.

kotlin
// Pagpapatunay: pamamaraan tinawag nang eksaktong 1 beses
verify(exactly = 1) { repo.save(any()) }

// Pagsusuri ng pagkakasunud-sunod ng mga tawag
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify para sa mga suspend-function
coVerify { api.fetchUsers() }

Slot: pagkuha ng mga argumento

Para sa pagsusuri ng mga argumento, ginagamit ang slot() — ang analog ng ArgumentCaptor. Ang slot ay idinedeklara bago ang tawag, ipinapasa sa every o verify, at pagkatapos ng pagpapatupad ng test ay naglalaman ng nakuhang halaga.

kotlin
val userSlot = slot<User>()

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

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

Mga anotasyon ng MockK at integrasyon ng JUnit

MockK ay nagbibigay ng mga anotasyon na @MockK at @RelaxedMockK para sa paggawa ng mga mock sa pamamagitan ng initialization sa JUnit 5. Ang extension na MockKExtension ay awtomatikong lumilikha ng mga mock bago ang bawat test at naglilinis pagkatapos — katulad ng MockitoExtension, ngunit may suporta para sa relaxed mode.

Halimbawa gamit ang MockKExtension

Ang anotasyon na @InjectMockKs (o ang alternatibong @MockK na may hayagang paggawa ng object) ay nag-i-inject ng mga mock sa nasubok na instance. Binabawasan nito ang boilerplate at ginagawang mas malinis ang code ng test.

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: ano ang pipiliin para sa Kotlin

Ang pagpili sa pagitan ng MockK at Mockito ay depende sa komposisyon ng team at uri ng proyekto. Ang Mockito ay may mas malaking ecosystem, mas maraming halimbawa at integrasyon, ngunit ang MockK ay nag-aalok ng mas malinis na Kotlin syntax at native na suporta para sa mga feature ng wika. Para sa mga bagong proyektong Kotlin, inirerekumenda ang MockK bilang mas idiomatic na solusyon.

KriterionMockKMockito
SyntaxKotlin DSL (every, verify)Estilo ng Java (when, thenReturn)
CoroutinecoEvery, coVerify (native)Nangangailangan ng karagdagang library
Final classSinusuportahan bilang defaultNangangailangan ng mockito-inline
KMPSinusuportahanHindi sinusuportahan
Relaxed mockBuilt-inWalang katumbas
PopularidadLumalaki sa komunidad ng KotlinNangingibabaw sa Java at hybrid na proyekto

Para sa mga proyekto sa purong Kotlin (walang Java classes), mas gusto ang MockK: mas kaunting boilerplate, native na suporta para sa coroutine, walang sorpresa sa mga final class. Para sa mga hybrid na proyekto o team na may background sa Java, nananatiling gumaganang opsyon ang Mockito — ang parehong library ay maaaring gamitin sa isang proyekto sa pamamagitan ng iba't ibang module. Sa paglipat mula Mockito patungong MockK, sapat na upang palitan ang mga anotasyon na @Mock ng @MockK at muling isulat ang mga bloke na when().thenReturn() sa format na every { }.

Mga Madalas Itanong

Ano ang pagkakaiba ng relaxed mock sa ordinaryong mock sa MockK?

Relaxed mock ay nagbabalik ng mga default na halaga para sa lahat ng hindi naka-stub na pamamaraan (walang laman na listahan, 0, null), nang hindi nagtatapon ng mga exception. Ang ordinaryong (strict) mock ay nangangailangan ng hayagang stubbing ng bawat pamamaraan — kung hindi, babagsak ang test. Ang relaxed mock ay maginhawa para sa mabilis na test, ang strict — para sa maaasahang test.

Paano i-mock ang mga extension-function sa MockK?

MockK ay sumusuporta sa pag-mock ng mga extension-function sa pamamagitan ng mockkStatic(). Ito ay posible dahil ang mga extension-function sa Kotlin ay mga static na pamamaraan na may unang parameter na tagatanggap. Para sa bawat extension-function, kailangang tukuyin ang klase kung saan ito idineklara.

Gumagana ba ang MockK sa Kotlin Multiplatform?

Oo, sinusuportahan ng MockK ang Kotlin Multiplatform (KMP) para sa common code. Sa mga platform na JVM, Native at JS, maaaring gamitin ang common API na mockk(), every, verify. Ginagawa nitong nag-iisang pagpipilian ang MockK para sa mga proyektong KMP kung saan hindi gumagana ang Mockito.

Paano suriin ang pagkakasunud-sunod ng mga tawag sa MockK?

Gamitin ang verifySequence { } — isang bloke kung saan ang mga tawag ay tinukoy nang mahigpit sa inaasahang pagkakasunud-sunod. Kung ang aktwal na pagkakasunud-sunod ay naiiba, ang verifySequence ay magtatapon ng exception na may indikasyon ng unang hindi tugmang tawag.

Maaari bang gamitin ang MockK at Mockito sa isang proyekto?

Oo, teknikal ito ay posible, ngunit hindi inirerekomenda. Maaaring lumitaw ang mga salungatan sa antas ng bytecode instrumentation (ByteBuddy vs mockito-inline). Kung ang proyekto ay gumagamit na ng Mockito, ang paglipat sa MockK ay maaaring gawin nang paunti-unti sa pamamagitan ng paghihiwalay ng mga module.

Buod

  • MockK — Kotlin-first library para sa mocking na may native na suporta sa wika.
  • every { } — deklaratibong DSL para sa pag-configure ng pag-uugali ng mga mock.
  • coEvery / coVerify — suporta para sa mga suspend-function ng coroutine nang walang karagdagang dependency.
  • Relaxed mock — mock na may mga default na halaga na nagbabawas ng boilerplate.
  • @MockK / @InjectMockKs — mga anotasyon para sa awtomatikong paggawa ng mock sa JUnit 5.
  • MockK vs Mockito — mas gusto ang MockK para sa purong Kotlin at KMP na proyekto.
  • verifySequence — pagsusuri ng mahigpit na pagkakasunud-sunod ng mga tawag sa pamamaraan.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din