Mokkery
The mocking library for Kotlin Multiplatform, easy to use, boilerplate-free and compiler plugin driven.
Why Mokkery?
- 🌿 Simple
- ⌚ Easy setup
- 🌍 Multiplatform
- 🖌️ Customizable
- 🧩 Extensible
class BookServiceTest {
val repository = mock<BookRepository> {
everySuspend { findById(any()) } calls { (id: String) -> Book(id) }
}
val service = BookService(repository)
@Test
fun `rent should call repository for each book`() = runTest {
service.rentAll(listOf("1", "2"))
verifySuspend(exhaustiveOrder) {
repository.findById("1")
repository.findById("2")
}
}
}
Just apply Gradle plugin and...
- K1
- K2
plugins {
kotlin("multiplatform") version "1.9.25" // ...or any other Kotlin plugin
id("dev.mokkery") version "1.9.25-1.7.0"
}
plugins {
kotlin("multiplatform") version "2.1.0" // ...or any other Kotlin plugin
id("dev.mokkery") version "2.6.1"
}
...that's it!
Please refer to the setup section, as additional configuration may be required in some cases!
- ☕ JVM & Android
- 🔧 All Kotlin Native targets
- 🌐 JS (Browser, Node.js)
- 🧪 Wasm-JS (Browser, Node.js)
- 🧪 Wasm-WASI (Node.js)
Change Mokkery strictness globally...
build.gradle.kts
mokkery {
defaultMockMode.set(autoUnit)
defaultVerifyMode.set(exhaustiveOrder)
}
...or locally!
FooTest.kt
class FooTest {
private val bar = mock<Bar>(autoUnit)
// ...
@Test
fun fooTest() {
// ...
verify (exhaustiveOrder) { /* ... */ }
}
}
Custom matchers!
// For any type!
inline fun <reified T : List<*>> ArgMatchersScope.hasSize(size: Int): T = matching(
toString = { "hasSize($size)" }, // prettify its presence!
predicate = { it.size == size }
)
// By function reference!
fun ArgMatchersScope.isNotEmpty(): String = matchingBy(String::isNotEmpty)
Custom answers!
// Custom answer for blocking functions!
fun BlockingAnsweringScope<Int>.randomInt() = calls { Random.nextInt() }
// Custom answer for suspending functions!
infix fun <T> SuspendAnsweringScope<T>.returnsDelayed(value: T) = calls {
delay(1_000)
value
}