MockK: co to jest, kluczowe pojęcia i składnia

Autor: IT Sectr Opublikowano: 2026-04-08 Czas czytania: 8 min

MockK — to framework Kotlin-first do tworzenia obiektów mock, zaprojektowany specjalnie dla ekosystemu Kotlin z uwzględnieniem jego cech językowych: korutyn, funkcji rozszerzających, data class i sealed class. W przeciwieństwie do Mockito, który został przeniesiony na Kotlin z Javy, MockK od początku był projektowany pod składnię Kotlina i nie wymaga dodatkowych wtyczek do pracy z klasami final. Według danych MockK.io, biblioteka jest używana w ponad 40% projektów Kotlin z testami jednostkowymi.

Najważniejsze

  • MockK — biblioteka zorientowana na Kotlin do mockowania z obsługą korutyn i funkcji językowych.
  • mockk() — główna metoda tworzenia obiektu mock, analogiczna do Mockito.mock().
  • every { } — blok do konfiguracji zachowania mocka (stubbing) w stylu deklaratywnym.
  • coEvery / coVerify — specjalne konstrukcje do pracy z suspend-funkcjami korutyn.
  • Relaxed mock — mock, który zwraca wartości domyślne bez jawnego stubbingu.

Czym jest MockK?

MockK — to biblioteka do tworzenia obiektów mock, napisana w Kotlin i zoptymalizowana pod jego składnię. Rozwiązuje te same zadania co Mockito — izolację testowanego kodu od zależności — ale robi to z wykorzystaniem konstrukcji specyficznych dla Kotlina: lambd, DSL, reified generics i suspend-funkcji.

Główna zaleta MockK nad przeniesionymi rozwiązaniami — natywne wsparcie Kotlina. W Mockito mockowanie final-class wymaga opt-in (mockito-inline), a metod statycznych — mockStatic. MockK obsługuje to domyślnie, ponieważ klasy Kotlina domyślnie są finalne, a obejście tego ograniczenia jest wbudowane w architekturę biblioteki.

Wersja 1.13.12 (2024) — stabilne wydanie, obsługujące Kotlin 2.0, kompilator K2 i projekty wieloplatformowe (KMP). MockK działa również z Kotlin/Native i Kotlin/JS, co czyni go jedynym wyborem dla projektów KMP, gdzie ani Mockito, ani EasyMock nie mają zastosowania.

MockK został zaprojektowany z uwzględnieniem specyfiki Kotlina i wykorzystuje możliwości języka — reified generics, DSL z lambdami, funkcje inline — aby zapewnić zwięzłe i bezpieczne typowo API bez utraty wydajności.

Jak działa MockK

Mechanizm MockK opiera się na instrumentacji bajtkodu za pomocą biblioteki ByteBuddy (podobnie jak Mockito), ale opakowuje ją w przyjazny dla Kotlina DSL. Zamiast łańcuchów when().thenReturn() MockK używa lambdowych bloków every { } i coEvery { }, które wyglądają jak naturalne rozszerzenie języka. Pod maską MockK przechwytuje wywołanie wewnątrz lambdy, analizuje metodę i argumenty przez refleksję i dopasowuje do zapisanych reguł stubbingu.

Podstawowa składnia MockK

Blok every { mock.method() } returns value czyta się jako „każdym razem, gdy metoda jest wywoływana, zwróć wartość”. Taki deklaratywny składnia jest bliższa stylowi Kotlina i eliminuje pomyłki z kolejnością argumentów w when(). Dzięki reified generics Kotlina, typ mocka jest wyprowadzany automatycznie bez jawnego określania klasy.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: każde wywołanie findById(1) zwraca użytkownika
every { repository.findById(1) } returns User("Alice")

// Wywołanie i weryfikacja
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: mniej boilerplate

W przeciwieństwie do Mockito, gdzie każdą metodę trzeba konfigurować jawnie, MockK obsługuje relaxed mock — mock, który zwraca „rozsądne” wartości domyślne dla dowolnej metody: pustą listę dla List, 0 dla Int, pusty ciąg znaków dla String. To radykalnie skraca ilość kodu przygotowawczego.

kotlin
// Relaxed mock — wszystkie metody zwracają wartości domyślne
val api = mockk<ApiService>(relaxed = true)

// Nie wymaga stubbingu — zwróci pustą listę
println(api.getUsers()) // []

Tworzenie mocków i zrelaksowanych mocków

MockK oferuje kilka sposobów tworzenia obiektów mock: mockk<T>() dla ścisłego mocka (każda metoda musi być jawnie skonfigurowana), mockk<T>(relaxed = true) dla zrelaksowanego mocka oraz spyk(obj) do tworzenia szpiega na rzeczywistym obiekcie.

FunkcjaTypZachowanie bez stubbingu
mockk()Ścisły mockWyrzuca wyjątek przy wywołaniu nie-ustawionej metody
mockk(relaxed = true)Zrelaksowany mockZwraca wartość domyślną
spyk()SzpiegWywołuje rzeczywistą metodę, jeśli nie skonfigurowano stuba
slot()Argument CaptorPrzechwytuje argument do weryfikacji

Wybór między ścisłym a zrelaksowanym mockiem zależy od kontekstu. Ścisły mock gwarantuje, że test nie używa metod, których zachowanie nie jest zdefiniowane — zwiększa to niezawodność. Zrelaksowany mock jest wygodny do szybkiego prototypowania testów, gdzie nie wszystkie zależności są istotne. W praktyce zaleca się zaczynać od ścisłego mocka i przełączać się na relaxed tylko wtedy, gdy stubbing zajmuje więcej linii niż sam test.

Stubbing: konfiguracja zachowania za pomocą bloku every

Blok every — to centralna konstrukcja stubbingu w MockK. Wewnątrz lambdy opisuje się wywołanie metody z konkretnymi argumentami, a następnie zwraca się wartość przez returns, wyrzuca wyjątek przez throws lub oblicza odpowiedź przez answers.

Różne sposoby stubbingu

MockK obsługuje wszystkie scenariusze potrzebne do testowania: zwracanie wartości, wyrzucanie wyjątku, obliczanie odpowiedzi na podstawie argumentów, wiele odpowiedzi po kolei (sekwencja wywołań).

kotlin
// Zwracanie wartości
every { repo.findById(1) } returns User("Alice")

// Rzucanie wyjątku
every { repo.findById(999) } throws NotFoundException()

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

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

Verify i coVerify dla korutyn

Verify w MockK jest analogiczny do Mockito.verify() w znaczeniu, ale używa DSL Kotlina: verify { mock.method() }. Dla suspend-funkcji używa się coVerify { mock.suspendMethod() }, który poprawnie działa z korutynami i nie wymaga specjalnego runnera.

Sprawdzanie liczby wywołań

MockK obsługuje te same modyfikatory co Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). Składnia jest minimalistyczna — modyfikator przekazywany jest jako pierwszy argument w verify { }.

kotlin
// Weryfikacja: metoda wywołana dokładnie 1 raz
verify(exactly = 1) { repo.save(any()) }

// Weryfikacja kolejności wywołań
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify dla funkcji suspend
coVerify { api.fetchUsers() }

Slot: przechwytywanie argumentów

Do weryfikacji argumentów używa się slot() — analogu ArgumentCaptor. Slot jest deklarowany przed wywołaniem, przekazywany do every lub verify, a po wykonaniu testu zawiera przechwyconą wartość.

kotlin
val userSlot = slot<User>()

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

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

Adnotacje MockK i integracja z JUnit

MockK udostępnia adnotacje @MockK i @RelaxedMockK do tworzenia mocków przez inicjalizację w JUnit 5. Rozszerzenie MockKExtension automatycznie tworzy mocki przed każdym testem i czyści po — analogicznie do MockitoExtension, ale z obsługą trybu relaxed.

Przykład z MockKExtension

Adnotacja @InjectMockKs (lub alternatywa @MockK z jawnym tworzeniem obiektu) wstrzykuje mocki do testowanego egzemplarza. To skraca boilerplate i czyni kod testu czystszym.

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: co wybrać dla Kotlin

Wybór między MockK a Mockito zależy od składu zespołu i typu projektu. Mockito ma większą ekosystem, więcej przykładów i integracji, ale MockK zapewnia czystszą składnię Kotlina i natywne wsparcie dla funkcji językowych. Dla nowych projektów Kotlin MockK jest zalecany jako bardziej idiomatyczne rozwiązanie.

KryteriumMockKMockito
SkładniaKotlin DSL (every, verify)Styl Java (when, thenReturn)
KorutynycoEvery, coVerify (natywnie)Wymaga dodatkowych bibliotek
Final classObsługiwane domyślnieWymaga mockito-inline
KMPObsługiwaneNieobsługiwane
Relaxed mockWbudowanyBrak odpowiednika
PopularnośćRosnąca w społeczności KotlinDominuje w Javie i projektach hybrydowych

Dla projektów w czystym Kotlinie (bez klas Java) MockK jest preferowany: mniej boilerplate, natywne wsparcie korutyn, brak niespodzianek z klasami final. Dla projektów hybrydowych lub zespołów z doświadczeniem w Javie Mockito pozostaje działającym rozwiązaniem — obie biblioteki mogą być używane w jednym projekcie przez różne moduły. Przy migracji z Mockito na MockK wystarczy zastąpić adnotacje @Mock na @MockK i przepisać bloki when().thenReturn() w format every { }.

Często zadawane pytania

Czym się różni relaxed mock od zwykłego mocka w MockK?

Relaxed mock zwraca wartości domyślne dla wszystkich nie-ustawionych metod (pusta lista, 0, null), nie wyrzucając wyjątków. Zwykły (strict) mock wymaga jawnego stubbingu każdej metody — w przeciwnym razie test pada. Relaxed mock jest wygodny do szybkich testów, strict — do niezawodnych.

Jak mockować funkcje rozszerzające w MockK?

MockK obsługuje mockowanie funkcji rozszerzających przez mockkStatic(). Jest to możliwe, ponieważ funkcje rozszerzające w Kotlinie są metodami statycznymi z pierwszym parametrem-odbiorcą. Dla każdej funkcji rozszerzającej należy określić klasę, w której jest zadeklarowana.

Czy MockK działa z Kotlin Multiplatform?

Tak, MockK obsługuje Kotlin Multiplatform (KMP) dla kodu wspólnego. Na platformach JVM, Native i JS można używać wspólnego API mockk(), every, verify. To czyni MockK jedynym wyborem dla projektów KMP, gdzie Mockito nie działa.

Jak sprawdzić kolejność wywołań w MockK?

Użyj verifySequence { } — bloku, w którym wywołania są określone ściśle w oczekiwanej kolejności. Jeśli rzeczywista kolejność się różni, verifySequence wyrzuci wyjątek z informacją o pierwszym niezgodnym wywołaniu.

Czy można używać MockK i Mockito w jednym projekcie?

Tak, technicznie jest to możliwe, ale nie zalecane. Konflikty mogą wystąpić na poziomie instrumentacji bajtkodu (ByteBuddy vs mockito-inline). Jeśli projekt już używa Mockito, migracja na MockK może być stopniowa poprzez izolację modułów.

Podsumowanie

  • MockK — biblioteka Kotlin-first do mockowania z natywnym wsparciem języka.
  • every { } — deklaratywny DSL do konfiguracji zachowania mocków.
  • coEvery / coVerify — wsparcie suspend-funkcji korutyn bez dodatkowych zależności.
  • Relaxed mock — mock z wartościami domyślnymi, skracający boilerplate.
  • @MockK / @InjectMockKs — adnotacje do automatycznego tworzenia mocków w JUnit 5.
  • MockK vs Mockito — MockK preferowany dla czystych projektów Kotlin i KMP.
  • verifySequence — sprawdzanie ścisłej kolejności wywołań metod.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również