MockK: bu nədir, əsas anlayışlar və sintaksis

Müəllif: IT Sectr Dərc olunub: 2026-04-08 Oxuma vaxtı: 8 dəq

MockK — bu Kotlin-first freymvorkdur mock-obyektləri yaratmaq üçün, Kotlin ekosistemi üçün xüsusilə onun dil xüsusiyyətləri nəzərə alınmaqla hazırlanmışdır: korutinlər, extension-funksiyalar, data class və sealed class. Java-dan Kotlin-ə port edilmiş Mockito-dan fərqli olaraq, MockK əvvəldən Kotlin sintaksisi üçün layihələndirilmişdir və final-klaslarla işləmək üçün əlavə plaginlər tələb etmir. MockK.io məlumatlarına görə, kitabxana vahid testlərlə Kotlin layihələrinin 40%-dən çoxunda istifadə olunur.

Əsas məqamlar

  • MockK — korutinlər və dil xüsusiyyətləri dəstəyi ilə Kotlin-yönümlü mock kitabxanası.
  • mockk() — Mockito.mock()-a bənzər şəkildə mock-obyekti yaratmağın əsas metodu.
  • every { } — bəyannamə üslubunda mock davranışını (stubbing) konfiqurasiya etmək üçün blok.
  • coEvery / coVerify — korutinlərin suspend-funksiyaları ilə işləmək üçün xüsusi konstruksiyalar.
  • Relaxed mock — açıq stubbing olmadan standart dəyərləri qaytaran mock.

MockK nədir?

MockK — bu Kotlin dilində yazılmış və onun sintaksisi üçün optimallaşdırılmış mock-obyektləri yaratma kitabxanasıdır. O, Mockito ilə eyni vəzifələri həll edir — test edilən kodu asılılıqlardan təcrid etmək — lakin bunu Kotlin-ə xas konstruksiyalardan istifadə edərək edir: lambdalar, DSL, reified generics və suspend-funksiyalar.

MockK-nın port edilmiş həllər üzərində əsas üstünlüyü Kotlin-in nativ dəstəyidir. Mockito-da final-klasların mock edilməsi opt-in tələb edir (mockito-inline), statik metodlar isə — mockStatic. MockK bunu standart olaraq dəstəkləyir, çünki Kotlin klasları standart olaraq finaldır və bu məhdudiyyətin aradan qaldırılması kitabxananın arxitekturasına daxil edilmişdir.

1.13.12 versiyası (2024) — Kotlin 2.0, K2-kompilyator və çoxplatformalı layihələri (KMP) dəstəkləyən sabit buraxılışdır. MockK həmçinin Kotlin/Native və Kotlin/JS ilə işləyir ki, bu da onu nə Mockito, nə də EasyMock-un tətbiq oluna bilmədiyi KMP layihələri üçün yeganə seçim edir.

MockK Kotlin-in spesifikasını nəzərə alaraq layihələndirilmişdir və dil imkanlarından — reified generics, lambdalarla DSL, inline-funksiyalar — məhsuldarlığı itirmədən yığcam və tip təhlükəsiz API təmin etmək üçün istifadə edir.

MockK necə işləyir

Mexanizm MockK ByteBuddy kitabxanası vasitəsilə baytkod-instrumentasiyasəna əsaslanır (Mockito kimi), lakin onu Kotlin-ə uyğun DSL-ə bürüyür. when().thenReturn() zəncirləri əvəzinə MockK every { } və coEvery { } lambda bloklarından istifadə edir ki, bunlar da dilin təbii genişlənməsi kimi görünür. Daxildə, MockK lambda daxilində çağırışı tutur, metodu və arqumentləri refleksiya vasitəsilə təhlil edir və qeyd edilmiş stubbing qaydaları ilə uyğumlaşdırır.

MockK-nın əsas sintaksisi

every { mock.method() } returns value bloku „hər dəfə metod çağırılanda dəyər qaytar” kimi oxunur. Bu bəyannamə sintaksisi Kotlin üslubuna daha yaxındır və when()-də arqumentlərin sırası ilə bağlı qarışıqlığı aradan qaldırır. Kotlin-in reified generics sayəsində, mock tipi sinfin açıq göstərilməsi olmadan avtomatik olaraq çıxarılır.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: hər findById(1) çağırışı istifadəçini qaytarır
every { repository.findById(1) } returns User("Alice")

// Çağırış və yoxlama
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: daha az boilerplate

Hər metodun açıq şəkildə konfiqurasiya edilməli olduğu Mockito-dan fərqli olaraq, MockK relaxed mock — istənilən metod üçün „məntıqlı” standart dəyərlər qaytaran mock-u dəstəkləyir: List üçün boş siyahı, Int üçün 0, String üçün boş sətr. Bu, hazırlıq kodunun həcmini kəskin şəkildə azaldır.

kotlin
// Relaxed mock — bütün metodlar standart dəyərlər qaytarır
val api = mockk<ApiService>(relaxed = true)

// Stubbing tələb etmir — boş siyahı qaytaracaq
println(api.getUsers()) // []

Mock və relaks edilmiş mockların yaradılması

MockK mock-obyektləri yaratmağın bir neçe üsulunu təklif edir: ciddi mock üçün mockk<T>() (hər metod açıq şəkildə konfiqurasiya edilməlidir), relaks edilmiş mock üçün mockk<T>(relaxed = true) və real obyekt üzərində casus yaratmaq üçün spyk(obj).

FunksiyaTipStubbing olmadan davranış
mockk()Ciddi mockStub edilməmiş metod çağırılanda istisna atır
mockk(relaxed = true)Relaks edilmiş mockStandart dəyər qaytarır
spyk()CasusStub konfiqurasiya edilməyibsə, real metodu çağırır
slot()Argument CaptorYoxlama üçün arqumenti tutur

Ciddi və relaks edilmiş mock arasında seçim kontekstdən asılıdır. Ciddi mock, testin davranışı müəyyən edilməmiş metodlardan istifadə etməməsini təmin edir — bu etibarlılığı artırır. Relaks edilmiş mock, bütün asılılıqların vacib olmadığı sürətli test prototipləşdirmə üçün əlverişlidir. Təcrübədə, ciddi mock-dan başlamaq və yalnız stubbing testin özündən daha çox sətir tutduqda relaxed-a keçmək tövsiyə olunur.

Stubbing: every bloku ilə davranışın konfiqurasiyası

Every bloku — MockK-da stubbing-in mərkəzi konstruksiyasıdır. Lambda daxilində konkret arqumentlərlə metod çağırışı təsvir edilir və sonra returns vasitəsilə dəyər qaytarılır, throws vasitəsilə istisna atılır və ya answers vasitəsilə cavab hesablanır.

Stubbing-in müxtəlif üsulları

MockK test üçün lazım olan bütün ssenariləri dəstəkləyir: dəyər qaytarma, istisna atma, arqumentlər əsasında cavab hesablama, ardıcıl çağırışlar üçün bir neçə cavab.

kotlin
// Dəyər qaytarma
every { repo.findById(1) } returns User("Alice")

// İstisna atma
every { repo.findById(999) } throws NotFoundException()

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

// Cavablar ardıcıllığı
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Korutinlər üçün Verify və coVerify

Verify MockK-da mənaca Mockito.verify()-a bənzərdir, lakin Kotlin DSL-dən istifadə edir: verify { mock.method() }. Suspend-funksiyalar üçün coVerify { mock.suspendMethod() } istifadə olunur ki, bu da korutinlərlə düzgün işləyir və xüsusi runner tələb etmir.

Çağırışların sayını yoxlama

MockK Mockito ilə eyni modifikatorları dəstəkləyir: exactly(1), atLeast(2), atMost(5), wasNot(Called). Sintaksis minimalistdir — modifikator verify { }-də ilk arqument kimi ötürülür.

kotlin
// Yoxlama: metod dəqiq 1 dəfə çağırıldı
verify(exactly = 1) { repo.save(any()) }

// Çağırış sırasını yoxlama
verifySequence {
    repo.save(any())
    repo.flush()
}

// Suspend-funksiyalar üçün coVerify
coVerify { api.fetchUsers() }

Slot: arqumentlərin tutulması

Arqumentləri yoxlamaq üçün slot() — ArgumentCaptor-un analoqu istifadə olunur. Slot çağırışdan əvvəl elan edilir, every və ya verify-ə ötürülür və test yerinə yetirildikdən sonra tutulmuş dəyəri ehtiva edir.

kotlin
val userSlot = slot<User>()

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

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

MockK annotasiyaları və JUnit inteqrasiyası

MockK JUnit 5-də inisializasiya vasitəsilə mocklar yaratmaq üçün @MockK@RelaxedMockK annotasiyalarını təqdim edir. MockKExtension genişləndirməsi hər testdən əvvəl avtomatik olaraq mocklar yaradır və sonra təmizləyir — MockitoExtension-a bənzərdir, lakin relaxed rejimi dəstəkləyir.

MockKExtension ilə nümunə

@InjectMockKs annotasiyası (və ya alternativ olaraq @MockK obyektin açıq yaradılması ilə) mockları test edilən nüsxəyə daxil edir. Bu, boilerplate-i azaldır və test kodunu təmizləyir.

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 üçün nə seçməli

Seçim MockK və Mockito arasında komandanın tərkibindən və layihə tipindən asılıdır. Mockito daha böyük ekosistemə, daha çox nümunə və inteqrasiyaya malikdir, lakin MockK daha təmiz Kotlin sintaksisi və dil xüsusiyyətlərinin nativ dəstəyini təmin edir. Yeni Kotlin layihələri üçün MockK daha idiomatik həll kimi tövsiyə olunur.

MeyarMockKMockito
SintaksisKotlin DSL (every, verify)Java stil (when, thenReturn)
KorutinlərcoEvery, coVerify (nativ)Əlavə kitabxanalar tələb edir
Final classStandart olaraq dəstəklənirmockito-inline tələb edir
KMPDəstəklənirDəstəklənmir
Relaxed mockDaxiliAnaloqu yoxdur
PopulyarlıqKotlin icmasında artırJava və hibrid layihələrdə üstünlük təşkil edir

Təmiz Kotlin layihələri üçün (Java klasları olmadan) MockK üstünlük təşkil edir: daha az boilerplate, korutinlərin nativ dəstəyi, final-klaslarla bağlı sürprizlər yoxdur. Hibrid layihələr və ya Java təcrübəsi olan komandalar üçün Mockito işlək variant olaraq qalır — hər iki kitabxana eyni layihədə müxtəlif modullar vasitəsilə istifadə edilə bilər. Mockito-dan MockK-a miqrasiya edərkən @Mock annotasiyalarını @MockK ilə əvəz etmək və when().thenReturn() bloklarını every { } formatına çevirmək kifayətdir.

Tez-tez verilən suallar

Relaxed mock adi mock-dan nə ilə fərqlənir?

Relaxed mock bütün stub edilməmiş metodlar üçün standart dəyərlər qaytarır (boş siyahı, 0, null), istisna atmadan. Adi (strict) mock hər metodun açıq stubbingini tələb edir — əks halda test uğursuz olur. Relaxed mock sürətli testlər üçün əlverişlidir, strict isə etibarlılıq üçün.

MockK-da extension-funksiyaları necə mock etmək olar?

MockK extension-funksiyaların mockkStatic() vasitəsilə mock edilməsini dəstəkləyir. Bu mümkündür, çünki Kotlin-də extension-funksiyalar ilk parametri qəbul edən statik metodlardır. Hər extension-funksiya üçün onun elan edildiyi sinif göstərilməlidir.

MockK Kotlin Multiplatform ilə işləyirmi?

Bəli, MockK ümumi kod üçün Kotlin Multiplatform (KMP) dəstəkləyir. JVM, Native və JS platformalarında ümumi API-dən istifadə etmək olar: mockk(), every, verify. Bu, MockK-nı Mockito-nun işləmədiyi KMP layihƏəri üçün yeganə seçim edir.

MockK-da çağırışların sırasını necə yoxlamaq olar?

verifySequence { } istifadə edin — çağırışların gözlənilən ardıcıllıqla göstərildiyi blok. Əgər real ardıcıllıq fərqlidirsə, verifySequence ilk uyğunsuz çağırışı göstərərək istisna atır.

Eyni layihədə MockK və Mockito istifadə etmək olarmı?

Bəli, texniki olaraq mümkündür, lakin tövsiyə edilmir. Münaqişələr baytkod-instrumentasiya səviyyəsində yarana bilər (ByteBuddy vs mockito-inline). Layihə artıq Mockito istifadə edirsə, MockK-a miqrasiya modulların izolyasiyası vasitəsilə tədricən həyata keçirilə bilər.

Nəticə

  • MockK — dilin nativ dəstəyi ilə Kotlin-first mock kitabxanası.
  • every { } — mock davranışını konfiqurasiya etmək üçün bəyannamə DSL.
  • coEvery / coVerify — əlavə asılılıqlar olmadan korutin suspend-funksiyalarının dəstəyi.
  • Relaxed mock — boilerplate-i azaldan standart dəyərləri olan mock.
  • @MockK / @InjectMockKs — JUnit 5-də avtomatik mock yaratma üçün annotasiyalar.
  • MockK vs Mockito — təmiz Kotlin və KMP layihələri üçün MockK üstünlük təşkil edir.
  • verifySequence — metod çağırışlarının ciddi ardıcıllığını yoxlama.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun