A Guide to MockK: a Mocking Library for Kotlin

1. Introduction

2. Prepare the Code For Testing

class ExampleClass {

fun multiplyByTen(number: Int) = 10 * number

fun publicFunction() = privateFunction()

private fun privateFunction() = "Returned value"
}

class Injected {
fun multiplyByFive(number: Int) = 5 * number
}

class ExampleClassWithDependency {

lateinit var injected: Injected

fun returnInjectedValue(number: Int) = injected.multiplyByFive(number)
}

object ExampleObject {
fun concat(one: String, two: String) = one + two
}

3. Imports

implementation("io.mockk:mockk:1.10.2")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.0")

3. Using MockK library

3.1. Mocking

@Test
fun `Mock a class`() {
val exampleClass = mockk()

every { exampleClass.publicFunction() } returns "Mocked value"

val result = exampleClass.publicFunction()

assertEquals("Mocked value", result)
}
@Test
fun `Mock a property of the class`() {
val injected = mockk()
val exampleClass = ExampleClassWithDependency()
exampleClass.injected = injected

every { injected.multiplyByFive(any()) } returns 7

val result = exampleClass.returnInjectedValue(10)

assertEquals(7, result)
}

3.2. Relaxed mock

@Test
fun `Example of MockKException`() {
val exampleClass = mockk()

exampleClass.publicFunction()
}
@Test
fun `Fix MockKException using relaxed mock`() {
val exampleClass = mockk(relaxed = true)
val defaultStringValue = ""

assertEquals(defaultStringValue, exampleClass.publicFunction())
}

3.3. Using Annotations

@ExtendWith(MockKExtension::class)
internal class ExampleClassTest
@MockK
lateinit var annotatedMock: Injected

@InjectMockKs
var annotatedClass = ExampleClassWithDependency()
@Test
fun `Simplified property mock with annotation`() {
every { annotatedMock.multiplyByFive(any()) } returns 7

val result = annotatedClass.returnInjectedValue(10)

assertEquals(7, result)
}

3.4. Spy The Object

@Test
fun `Spy a class`() {
val exampleClass = spyk()

assertEquals("Returned value", exampleClass.publicFunction())
}

3.5. Mock Private Function Behavior

@Test
fun `Mock a private function`() {
val exampleClass = spyk(recordPrivateCalls = true)

every { exampleClass["privateFunction"]() } returns "Mocked value"

assertEquals("Mocked value", exampleClass.publicFunction())
}

3.6. Mock an Object

@Test
fun `Mock an object`() {
mockkObject(ExampleObject)

every { ExampleObject.concat(any(), any()) } returns "Mocked value"

val result = ExampleObject.concat("", "")
assertEquals("Mocked value", result)
}
@Test
fun `Multiple mocked instances of object`() {
val firstMock = mockk()
val secondMock = mockk()

every { firstMock.concat(any(), any()) } returns "One"
every { secondMock.concat(any(), any()) } returns "Two"

val firstResult = firstMock.concat("", "")
val secondResult = secondMock.concat("", "")

assertEquals("One", firstResult)
assertEquals("Two", secondResult)
}

3.7. Capturing

@Test
fun `Capture passed value`() {
val exampleClassMock = mockk()
val argumentSlot = slot()

every { exampleClassMock.multiplyByTen(capture(argumentSlot)) } returns 5

exampleClassMock.multiplyByTen(55)

assertEquals(55, argumentSlot.captured)
}

3.8. Verification

@Test
fun `Verify calls`() {
val exampleClassMock = mockk()

every { exampleClassMock.multiplyByTen(any()) } returns 5

exampleClassMock.multiplyByTen(10)
exampleClassMock.multiplyByTen(20)

verify(exactly = 2) { exampleClassMock.multiplyByTen(any()) }
confirmVerified(exampleClassMock)
}

4. Summary

Hi, my name is Piotr and I am the founder of Codersee- a technical blog, where I am teaching programming by practical step by step tutorials.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store