Careeroza
Mocking with MockK
Why MockK
MockK is a mocking library written for Kotlin. Unlike Mockito it handles final classes, objects, extension functions and suspend functions out of the box.
| MockK | Meaning |
|---|---|
mockk<T>() | strict mock: un-stubbed calls throw |
mockk<T>(relaxed = true) | returns default values for everything |
every { ... } returns x | stub a normal function |
coEvery { ... } returns x | stub a suspend function |
verify { ... } / coVerify { ... } | check a call happened (exactly = 1, atLeast...) |
slot<T>() + capture(slot) | capture the argument for assertions |
spyk(obj) | real object with some functions stubbed |
Example
class CheckoutServiceTest {
private val payments = mockk<PaymentGateway>()
private val orders = mockk<OrderRepository>(relaxed = true)
private val service = CheckoutService(payments, orders)
@Test
fun `saves order after successful payment`() = runTest {
coEvery { payments.charge(any(), 799) } returns PaymentResult.Success("pay_123")
val saved = slot<Order>()
coEvery { orders.save(capture(saved)) } just Runs
service.checkout(userId = 7, amount = 799)
coVerify(exactly = 1) { payments.charge(7, 799) }
assertEquals("pay_123", saved.captured.paymentId)
}
@Test
fun `does not save order when payment fails`() = runTest {
coEvery { payments.charge(any(), any()) } throws PaymentDeclinedException("insufficient funds")
assertThrows<PaymentDeclinedException> { service.checkout(7, 799) }
coVerify(exactly = 0) { orders.save(any()) }
}
}Tip: Prefer fakes (small hand-written implementations) for repositories you use in many tests, and mocks for verifying one interaction (was the payment charged exactly once?). Over-mocking makes tests break on every refactor.