MockK: apa itu, konsep kunci dan sintaksis

Penulis: IT Sectr Diterbitkan: 2026-04-08 Waktu membaca: 8 mnt

MockK — adalah framework Kotlin-first untuk membuat objek mock, dirancang khusus untuk ekosistem Kotlin dengan mempertimbangkan fitur bahasanya: korutin, fungsi ekstensi, data class dan sealed class. Berbeda dengan Mockito yang di-porting ke Kotlin dari Java, MockK sejak awal dirancang untuk sintaksis Kotlin dan tidak memerlukan plugin tambahan untuk bekerja dengan kelas final. Menurut data MockK.io, pustaka ini digunakan di lebih dari 40% proyek Kotlin dengan pengujian unit.

Poin Utama

  • MockK — pustaka berorientasi Kotlin untuk mocking dengan dukungan korutin dan fitur bahasa.
  • mockk() — metode utama membuat objek mock, mirip dengan Mockito.mock().
  • every { } — blok untuk mengonfigurasi perilaku mock (stubbing) dalam gaya deklaratif.
  • coEvery / coVerify — konstruksi khusus untuk bekerja dengan fungsi suspend korutin.
  • Relaxed mock — mock yang mengembalikan nilai default tanpa stubbing eksplisit.

Apa itu MockK?

MockK — adalah pustaka untuk membuat objek mock, ditulis dalam Kotlin dan dioptimalkan untuk sintaksisnya. Ini memecahkan tugas yang sama seperti Mockito — isolasi kode yang diuji dari dependensi — tetapi melakukannya menggunakan konstruksi khusus Kotlin: lambda, DSL, reified generics dan fungsi suspend.

Keuntungan utama MockK dibandingkan solusi yang di-porting — dukungan asli Kotlin. Di Mockito, mocking kelas final memerlukan opt-in (mockito-inline), dan metode statis memerlukan mockStatic. MockK mendukung ini secara default, karena kelas Kotlin secara default adalah final, dan penanganan keterbatasan ini sudah dibangun ke dalam arsitektur pustaka.

Versi 1.13.12 (2024) — rilis stabil yang mendukung Kotlin 2.0, kompiler K2 dan proyek multi-platform (KMP). MockK juga bekerja dengan Kotlin/Native dan Kotlin/JS, menjadikannya satu-satunya pilihan untuk proyek KMP di mana Mockito maupun EasyMock tidak dapat diterapkan.

MockK dirancang dengan mempertimbangkan kekhususan Kotlin dan menggunakan kemampuan bahasa — reified generics, DSL dengan lambda, fungsi inline — untuk memberikan API yang ringkas dan aman tipe tanpa kehilangan kinerja.

Bagaimana MockK bekerja

Mekanisme MockK didasarkan pada instrumentasi bytecode melalui pustaka ByteBuddy (seperti Mockito), tetapi membungkusnya dalam DSL yang ramah Kotlin. Alih-alih rantai when().thenReturn(), MockK menggunakan blok lambda every { } dan coEvery { }, yang terlihat seperti perluasan alami bahasa. Di balik layar, MockK mencegat panggilan di dalam lambda, menganalisis metode dan argumen melalui refleksi dan mencocokannya dengan aturan stubbing yang tercatat.

Sintaksis dasar MockK

Blok every { mock.method() } returns value dibaca sebagai “setiap kali metode dipanggil, kembalikan nilainya”. Sintaksis deklaratif semacam ini lebih dekat dengan gaya Kotlin dan menghilangkan kebingungan dengan urutan argumen di when(). Berkat reified generics Kotlin, tipe mock disimpulkan secara otomatis tanpa spesifikasi kelas eksplisit.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: setiap panggilan findById(1) mengembalikan pengguna
every { repository.findById(1) } returns User("Alice")

// Panggilan dan verifikasi
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: lebih sedikit boilerplate

Berbeda dengan Mockito, di mana setiap metode harus dikonfigurasi secara eksplisit, MockK mendukung relaxed mock — mock yang mengembalikan nilai default “masuk akal” untuk metode apa pun: daftar kosong untuk List, 0 untuk Int, string kosong untuk String. Ini secara drastis mengurangi jumlah kode persiapan.

kotlin
// Relaxed mock — semua metode mengembalikan nilai default
val api = mockk<ApiService>(relaxed = true)

// Tidak memerlukan stubbing — akan mengembalikan daftar kosong
println(api.getUsers()) // []

Membuat mock dan mock rileks

MockK menawarkan beberapa cara untuk membuat objek mock: mockk<T>() untuk mock ketat (setiap metode harus dikonfigurasi secara eksplisit), mockk<T>(relaxed = true) untuk mock rileks dan spyk(obj) untuk membuat spy pada objek nyata.

FungsiTipePerilaku tanpa stubbing
mockk()Mock ketatMelempar pengecualian saat metode non-stub dipanggil
mockk(relaxed = true)Mock rileksMengembalikan nilai default
spyk()SpyMemanggil metode nyata jika stub tidak dikonfigurasi
slot()Argument CaptorMenangkap argumen untuk verifikasi

Pilihan antara mock ketat dan rileks tergantung pada konteksnya. Mock ketat memastikan bahwa tes tidak menggunakan metode yang perilakunya tidak ditentukan — ini meningkatkan keandalan. Mock rileks nyaman untuk pembuatan prototipe cepat tes di mana tidak semua dependensi penting. Dalam praktiknya, disarankan untuk memulai dengan mock ketat dan beralih ke relaxed hanya ketika stubbing memakan lebih banyak baris daripada tes itu sendiri.

Stubbing: mengonfigurasi perilaku dengan blok every

Blok every — adalah konstruksi sentral stubbing di MockK. Di dalam lambda, panggilan metode dengan argumen tertentu dijelaskan, dan kemudian nilai dikembalikan melalui returns, pengecualian dilemparkan melalui throws atau jawaban dihitung melalui answers.

Berbagai cara stubbing

MockK mendukung semua skenario yang diperlukan untuk pengujian: mengembalikan nilai, melempar pengecualian, menghitung jawaban berdasarkan argumen, beberapa jawaban secara berurutan (urutan panggilan).

kotlin
// Mengembalikan nilai
every { repo.findById(1) } returns User("Alice")

// Melempar pengecualian
every { repo.findById(999) } throws NotFoundException()

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

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

Verify dan coVerify untuk korutin

Verify di MockK secara konsep analog dengan Mockito.verify() tetapi menggunakan DSL Kotlin: verify { mock.method() }. Untuk fungsi suspend digunakan coVerify { mock.suspendMethod() }, yang bekerja dengan benar dengan korutin dan tidak memerlukan runner khusus.

Memeriksa jumlah panggilan

MockK mendukung pengubah yang sama seperti Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). Sintaksisnya minimalis — pengubah dilewatkan sebagai argumen pertama di verify { }.

kotlin
// Verifikasi: metode dipanggil tepat 1 kali
verify(exactly = 1) { repo.save(any()) }

// Memeriksa urutan panggilan
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify untuk fungsi suspend
coVerify { api.fetchUsers() }

Slot: menangkap argumen

Untuk memeriksa argumen digunakan slot() — analog dari ArgumentCaptor. Slot dideklarasikan sebelum panggilan, dilewatkan ke every atau verify, dan setelah eksekusi tes berisi nilai yang ditangkap.

kotlin
val userSlot = slot<User>()

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

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

Anotasi MockK dan integrasi JUnit

MockK menyediakan anotasi @MockK dan @RelaxedMockK untuk membuat mock melalui inisialisasi di JUnit 5. Ekstensi MockKExtension secara otomatis membuat mock sebelum setiap tes dan membersihkan setelahnya — mirip dengan MockitoExtension, tetapi dengan dukungan mode relaxed.

Contoh dengan MockKExtension

Anotasi @InjectMockKs (atau alternatif @MockK dengan pembuatan objek eksplisit) menyuntikkan mock ke dalam instance yang diuji. Ini mengurangi boilerplate dan membuat kode tes lebih bersih.

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: apa yang harus dipilih untuk Kotlin

Pilihan antara MockK dan Mockito tergantung pada komposisi tim dan jenis proyek. Mockito memiliki ekosistem yang lebih besar, lebih banyak contoh dan integrasi, tetapi MockK menawarkan sintaksis Kotlin yang lebih bersih dan dukungan asli untuk fitur bahasa. Untuk proyek Kotlin baru, MockK direkomendasikan sebagai solusi yang lebih idiomatis.

KriteriaMockKMockito
SintaksisDSL Kotlin (every, verify)Gaya Java (when, thenReturn)
KorutincoEvery, coVerify (asli)Memerlukan pustaka tambahan
Final classDidukung secara defaultMemerlukan mockito-inline
KMPDidukungTidak didukung
Relaxed mockBawaanTidak ada padanan
PopularitasBerkembang di komunitas KotlinMendominasi di Java dan proyek hibrida

Untuk proyek Kotlin murni (tanpa kelas Java), MockK lebih disukai: lebih sedikit boilerplate, dukungan asli korutin, tidak ada kejutan dengan kelas final. Untuk proyek hibrida atau tim dengan latar belakang Java, Mockito tetap menjadi opsi yang berfungsi — kedua pustaka dapat digunakan dalam satu proyek melalui modul yang berbeda. Saat migrasi dari Mockito ke MockK, cukup ganti anotasi @Mock dengan @MockK dan tulis ulang blok when().thenReturn() ke format every { }.

Pertanyaan yang Sering Diajukan

Apa perbedaan relaxed mock dengan mock biasa di MockK?

Relaxed mock mengembalikan nilai default untuk semua metode non-stub (daftar kosong, 0, null), tanpa melempar pengecualian. Mock biasa (strict) memerlukan stubbing eksplisit setiap metode — jika tidak, tes gagal. Relaxed mock nyaman untuk tes cepat, strict — untuk tes andal.

Bagaimana cara mock fungsi ekstensi di MockK?

MockK mendukung mocking fungsi ekstensi melalui mockkStatic(). Ini dimungkinkan karena fungsi ekstensi di Kotlin adalah metode statis dengan parameter penerima pertama. Untuk setiap fungsi ekstensi, kelas tempat fungsi tersebut dideklarasikan harus ditentukan.

Apakah MockK bekerja dengan Kotlin Multiplatform?

Ya, MockK mendukung Kotlin Multiplatform (KMP) untuk kode umum. Di platform JVM, Native dan JS, API umum mockk(), every, verify dapat digunakan. Ini menjadikan MockK satu-satunya pilihan untuk proyek KMP di mana Mockito tidak berfungsi.

Bagaimana cara memeriksa urutan panggilan di MockK?

Gunakan verifySequence { } — blok di mana panggilan ditentukan secara ketat dalam urutan yang diharapkan. Jika urutan aktual berbeda, verifySequence akan melempar pengecualian dengan menunjukkan panggilan pertama yang tidak cocok.

Bisakah MockK dan Mockito digunakan dalam satu proyek?

Ya, secara teknis dimungkinkan, tetapi tidak disarankan. Konflik dapat terjadi pada tingkat instrumentasi bytecode (ByteBuddy vs mockito-inline). Jika proyek sudah menggunakan Mockito, migrasi ke MockK dapat dilakukan secara bertahap melalui isolasi modul.

Kesimpulan

  • MockK — pustaka Kotlin-first untuk mocking dengan dukungan bahasa asli.
  • every { } — DSL deklaratif untuk mengonfigurasi perilaku mock.
  • coEvery / coVerify — dukungan fungsi suspend korutin tanpa dependensi tambahan.
  • Relaxed mock — mock dengan nilai default yang mengurangi boilerplate.
  • @MockK / @InjectMockKs — anotasi untuk pembuatan mock otomatis di JUnit 5.
  • MockK vs Mockito — MockK lebih disukai untuk proyek Kotlin murni dan KMP.
  • verifySequence — pemeriksaan urutan ketat panggilan metode.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga