MockK: bu nima, asosiy tushunchalar va sintaksis

Muallif: IT Sectr Nashr etilgan: 2026-04-08 O'qish vaqti: 8 daq

MockK — bu Kotlin-first freymvork bo'lib, mock-obyektlar yaratish uchun mo'ljallangan va Kotlin ekotizimi uchun uning til xususiyatlarini hisobga olgan holda ishlab chiqilgan: korutinlar, extension-funksiyalar, data class va sealed class. Java-dan Kotlin-ga port qilingan Mockito-dan farqli o'laroq, MockK boshidanoq Kotlin sintaksisi uchun yaratilgan va final-klasslar bilan ishlash uchun qo'shimcha plaginlarni talab qilmaydi. MockK.io ma'lumotlariga ko'ra, kutubxona modul testlari bilan Kotlin loyihalarining 40% dan ko'prog'ida qo'llaniladi.

Asosiy ma'lumotlar

  • MockK — korutinlar va til xususiyatlarini qo'llab-quvvatlaydigan Kotlin-yo'naltirilgan mock kutubxonasi.
  • mockk() — Mockito.mock()-ga o'xshash mock-obyektni yaratishning asosiy usuli.
  • every { } — deklarativ uslubda mock xatti-harakatini (stubbing) sozlash uchun blok.
  • coEvery / coVerify — korutinlarning suspend-funksiyalari bilan ishlash uchun maxsus konstruksiyalar.
  • Relaxed mock — aniq stubbingsiz standart qiymatlarni qaytaradigan mock.

MockK nima?

MockK — bu Kotlin tilida yozilgan va uning sintaksisi uchun optimallashtirilgan mock-obyektlarni yaratish kutubxonasi. U Mockito bilan bir xil vazifalarni hal qiladi — test qilinayotgan kodni bog'liqliklardan izolyatsiya qilish — lekin buni Kotlin-ga xos konstruksiyalar yordamida amalga oshiradi: lambdalar, DSL, reified generics va suspend-funksiyalar.

MockK-ning port qilingan yechimlarga nisbatan asosiy afzalligi — Kotlin-ning native qo'llab-quvvatlanishi. Mockito-da final-klasslarni mock qilish opt-in talab qiladi (mockito-inline), statik usullar esa — mockStatic. MockK buni standart sifatida qo'llab-quvvatlaydi, chunki Kotlin klasslari standart sifatida final hisoblanadi va bu cheklovni chetlab o'tish kutubxona arxitekturasiga o'rnatilgan.

1.13.12 versiyasi (2024) — Kotlin 2.0, K2 kompilyator va ko'p platformali loyihalarni (KMP) qo'llab-quvvatlaydigan barqaror reliz. MockK shuningdek Kotlin/Native va Kotlin/JS bilan ishlaydi, bu esa uni Mockito ham, EasyMock ham qo'llanilmaydigan KMP loyihalari uchun yagona tanlovga aylantiradi.

MockK Kotlin-ning o'ziga xosligini hisobga olgan holda ishlab chiqilgan va til imkoniyatlaridan — reified generics, lambdalar bilan DSL, inline funksiyalar — unumdorlikni yo'qotmasdan ixcham va tip-xavfsiz API ta'minlash uchun foydalanadi.

MockK qanday ishlaydi

Mexanizm MockK ByteBuddy kutubxonasi orqali baytkod-instrumentatsiyasiga asoslanadi (Mockito kabi), lekin uni Kotlin-ga mos DSL-ga o'raydi. when().thenReturn() zanjirlari o'rniga MockK every { } va coEvery { } lambda bloklaridan foydalanadi, ular tilning tabiiy kengaytmasi sifatida ko'rinadi. Ichkarida, MockK lambda ichidagi chaqiruvni tutadi, usul va argumentlarni refleksiya orqali tahlil qiladi va ularni yozilgan stubbing qoidalariga moslashtiradi.

MockK-ning asosiy sintaksisi

every { mock.method() } returns value bloki "har safar usul chaqirilganda, qiymatni qaytar" deb o'qiladi. Bunday deklarativ sintaksis Kotlin uslubiga yaqinroq va when() dagi argumentlar tartibi bilan chalkashlikni bartaraf qiladi. Kotlin-ning reified generics tufayli, mock turi klassni aniq ko'rsatmasdan avtomatik ravishda chiqariladi.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: har bir findById(1) chaqiruvi foydalanuvchini qaytaradi
every { repository.findById(1) } returns User("Alice")

// Chaqiruv va tekshirish
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: kamroq boilerplate

Har bir usulni aniq sozlash kerak bo'lgan Mockito-dan farqli o'laroq, MockK relaxed mock — har qanday usul uchun "oqilona" standart qiymatlarni qaytaradigan mock-ni qo'llab-quvvatlaydi: List uchun bo'sh ro'yxat, Int uchun 0, String uchun bo'sh qator. Bu tayyorgarlik kodining hajmini keskin kamaytiradi.

kotlin
// Relaxed mock — barcha usullar standart qiymatlarni qaytaradi
val api = mockk<ApiService>(relaxed = true)

// Stubbing talab qilmaydi — bo'sh ro'yxatni qaytaradi
println(api.getUsers()) // []

Mock va relaksatsiyalangan mocklarni yaratish

MockK mock-obyektlarni yaratishning bir necha usullarini taklif qiladi: qattiq mock uchun mockk<T>() (har bir usul aniq sozlanishi kerak), relaksatsiyalangan mock uchun mockk<T>(relaxed = true) va haqiqiy obyektda josus yaratish uchun spyk(obj).

FunksiyaTurStubbingsiz xatti-harakat
mockk()Qattiq mockStub qilinmagan usul chaqirilganda istisno tashlaydi
mockk(relaxed = true)Relaksatsiyalangan mockStandart qiymatni qaytaradi
spyk()JosusStub sozlanmagan bo'lsa, haqiqiy usulni chaqiradi
slot()Argument CaptorTekshirish uchun argumentni ushlaydi

Qattiq va relaksatsiyalangan mock o'rtasidagi tanlov kontekstga bog'liq. Qattiq mock testning xatti-harakati aniqlanmagan usullardan foydalanmasligini kafolatlaydi — bu ishonchlilikni oshiradi. Relaksatsiyalangan mock barcha bog'liqliklar muhim bo'lmagan tezkor test prototiplash uchun qulay. Amalda, qattiq mockdan boshlash va faqat stubbing testning o'zidan ko'proq satrni egallaganida relaxed-ga o'tish tavsiya etiladi.

Stubbing: every bloki bilan xatti-harakatni sozlash

Every bloki — MockK-da stubbingning markaziy konstruksiyasi. Lambda ichida aniq argumentlar bilan usul chaqiruvi tasvirlanadi, so'ngra returns orqali qiymat qaytariladi, throws orqali istisno tashlanadi yoki answers orqali javob hisoblanadi.

Stubbingning turli usullari

MockK test uchun zarur bo'lgan barcha stsenariylarni qo'llab-quvvatlaydi: qiymat qaytarish, istisno tashlash, argumentlar asosida javob hisoblash, ketma-ket bir nechta javoblar (chaqiruvlar ketma-ketligi).

kotlin
// Qiymat qaytarish
every { repo.findById(1) } returns User("Alice")

// Istisno tashlash
every { repo.findById(999) } throws NotFoundException()

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

// Javoblar ketma-ketligi
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Korutinlar uchun Verify va coVerify

Verify MockK-da ma'nosi bo'yicha Mockito.verify()-ga o'xshaydi, lekin Kotlin DSL-dan foydalanadi: verify { mock.method() }. Suspend-funksiyalar uchun coVerify { mock.suspendMethod() } ishlatiladi, u korutinlar bilan to'g'ri ishlaydi va maxsus runner talab qilmaydi.

Chaqiruvlar sonini tekshirish

MockK Mockito bilan bir xil modifikatorlarni qo'llab-quvvatlaydi: exactly(1), atLeast(2), atMost(5), wasNot(Called). Sintaksis minimalist — modifikator verify { } da birinchi argument sifatida uzatiladi.

kotlin
// Tekshirish: usul aniq 1 marta chaqirildi
verify(exactly = 1) { repo.save(any()) }

// Chaqiruvlar tartibini tekshirish
verifySequence {
    repo.save(any())
    repo.flush()
}

// Suspend funksiyalar uchun coVerify
coVerify { api.fetchUsers() }

Slot: argumentlarni ushlash

Argumentlarni tekshirish uchun slot() — ArgumentCaptor analogi ishlatiladi. Slot chaqiruvdan oldin e'lon qilinadi, every yoki verify ga uzatiladi va test bajarilgandan so'ng ushlangan qiymatni o'z ichiga oladi.

kotlin
val userSlot = slot<User>()

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

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

MockK annotatsiyalari va JUnit integratsiyasi

MockK JUnit 5 da initsializatsiya orqali mocklar yaratish uchun @MockK va @RelaxedMockK annotatsiyalarini taqdim etadi. MockKExtension kengaytmasi har bir testdan oldin avtomatik ravishda mocklar yaratadi va keyin tozalaydi — MockitoExtension-ga o'xshash, lekin relaxed rejimini qo'llab-quvvatlaydi.

MockKExtension bilan misol

@InjectMockKs annotatsiyasi (yoki obyektni aniq yaratish bilan @MockK muqobili) mocklarni test qilinayotgan nusxaga kiritadi. Bu boilerplate-ni kamaytiradi va test kodini toza qiladi.

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 uchun nimani tanlash kerak

Tanlov MockK va Mockito o'rtasida jamoa tarkibi va loyiha turiga bog'liq. Mockito kattaroq ekotizimga, ko'proq misollar va integratsiyalarga ega, ammo MockK tozaroq Kotlin sintaksisi va til xususiyatlarining native qo'llab-quvvatlanishini ta'minlaydi. Yangi Kotlin loyihalari uchun MockK ko'proq idiomatik yechim sifatida tavsiya etiladi.

MezonMockKMockito
SintaksisKotlin DSL (every, verify)Java uslubi (when, thenReturn)
KorutinlarcoEvery, coVerify (native)Qo'shimcha kutubxonalar talab qiladi
Final classStandart sifatida qo'llab-quvvatlanadimockito-inline talab qiladi
KMPQo'llab-quvvatlanadiQo'llab-quvvatlanmaydi
Relaxed mockIchkiAnalogi yo'q
MashhurlikKotlin jamoasida o'sib bormoqdaJava va gibrid loyihalarda ustunlik qiladi

Sof Kotlin loyihalari uchun (Java klasslarisiz) MockK afzal: kamroq boilerplate, korutinlarning native qo'llab-quvvatlanishi, final-klasslar bilan kutilmagan hodisalar yo'q. Gibrid loyihalar yoki Java tajribasiga ega jamoalar uchun Mockito ishlaydigan variant bo'lib qoladi — ikkala kutubxona ham bir loyihada turli modullar orqali ishlatilishi mumkin. Mockito-dan MockK-ga migratsiya qilishda @Mock annotatsiyalarini @MockK bilan almashtirish va when().thenReturn() bloklarini every { } formatiga o'zgartirish kifoya.

Tez-tez beriladigan savollar

Relaxed mock oddiy mockdan nimasi bilan farq qiladi?

Relaxed mock barcha stub qilinmagan usullar uchun standart qiymatlarni qaytaradi (bo'sh ro'yxat, 0, null), istisno tashlamasdan. Oddiy (strict) mock har bir usulning aniq stubbingini talab qiladi — aks holda test muvaffaqiyatsiz bo'ladi. Relaxed mock tezkor testlar uchun qulay, strict — ishonchli testlar uchun.

MockK-da extension-funksiyalarni qanday mock qilish mumkin?

MockK extension-funksiyalarni mockkStatic() orqali mock qilishni qo'llab-quvvatlaydi. Bu mumkin, chunki Kotlin-dagi extension-funksiyalar birinchi parametr qabul qiluvchi statik usullardir. Har bir extension-funksiya uchun u e'lon qilingan klassni ko'rsatish kerak.

MockK Kotlin Multiplatform bilan ishlaydimi?

Ha, MockK umumiy kod uchun Kotlin Multiplatform (KMP) ni qo'llab-quvvatlaydi. JVM, Native va JS platformalarida umumiy API dan foydalanish mumkin: mockk(), every, verify. Bu MockK-ni Mockito ishlamaydigan KMP loyihalari uchun yagona tanlovga aylantiradi.

MockK-da chaqiruvlar tartibini qanday tekshirish mumkin?

verifySequence { } dan foydalaning — chaqiruvlar kutilgan tartibda qat'iy ko'rsatilgan blok. Haqiqiy tartib farq qilsa, verifySequence birinchi mos kelmaydigan chaqiruvni ko'rsatib, istisno tashlaydi.

Bir loyihada MockK va Mockito-ni birgalikda ishlatish mumkinmi?

Ha, texnik jihatdan mumkin, ammo tavsiya etilmaydi. Mojarolar baytkod-instrumentatsiya darajasida yuzaga kelishi mumkin (ByteBuddy vs mockito-inline). Agar loyiha allaqachon Mockito-dan foydalanayotgan bo'lsa, MockK-ga migratsiya modullarni izolyatsiya qilish orqali bosqichma-bosqich amalga oshirilishi mumkin.

Xulosa

  • MockK — tilning native qo'llab-quvvatlashi bilan Kotlin-first mock kutubxonasi.
  • every { } — mocklar xatti-harakatini sozlash uchun deklarativ DSL.
  • coEvery / coVerify — qo'shimcha bog'liqliklarsiz korutin suspend-funksiyalarini qo'llab-quvvatlash.
  • Relaxed mock — boilerplate-ni kamaytiradigan standart qiymatlarga ega mock.
  • @MockK / @InjectMockKs — JUnit 5 da avtomatik mock yaratish uchun annotatsiyalar.
  • MockK vs Mockito — sof Kotlin va KMP loyihalari uchun MockK afzal.
  • verifySequence — usul chaqiruvlari tartibini qat'iy tekshirish.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing