At this point, we spent a lot of time exploring MockK features and syntax, so at this point, adding coroutines will be trivial, trust me
Of course, you can find the rest of the series on my blog, too:
Getting Started with MockK in Kotlin [1/5]
MockK: Objects, Top-Level, and Extension Functions [3/5]
MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]
MockK with Coroutines [5/5]
Additional Imports
As the first step, let’s add the necessary import:
testImplementation(«org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.1»)
This package provides utilities for testing coroutines.
And thanks to that, we can mock and test suspend functions.
Code To Test
Following, let’s introduce the suspended functions:
class Eight(
private val one: EightOne,
private val two: EightTwo,
) {
suspend fun funToTest(): String {
return «${one.returnInt()} ${two.returnString()}»
}
}
class EightOne {
suspend fun returnInt(): Int = 10
}
class EightTwo {
suspend fun returnString(): String = «Some String»
}
And I know it does not make sense. But it is not important here
The important part is that we have suspended functions so we can start implementing tests.
MockK with Coroutines
As the next step, let’s try to implement the test “the old way”:
class EightTest {
private val one: EightOne = mockk()
private val two: EightTwo = mockk()
private val eight = Eight(one, two)
@Test
fun `should return 1 codersee`() {
every { one.returnInt() } returns 1
every { two.returnString() } returns «codersee»
val result = eight.funToTest()
assertEquals(«1 codersee», result)
verifySequence {
one.returnInt()
two.returnString()
}
}
}
As a result, we can see the compiler complaining about our suspended functions:
Suspend function ‘returnInt’ should be called only from a coroutine or another suspend function
Suspend function ‘returnString’ should be called only from a coroutine or another suspend function
Suspend function ‘funToTest’ should be called only from a coroutine or another suspend function
So, as the first step, let’s add the runTest to get rid of the last error:
@Test
fun `should return 1 codersee`() = runTest {
The runTest is not related to the MockK itself. It comes from kotlinx.coroutines and executes our test body in a new coroutine, returning TestResult .
When it comes to MockK, then we can work with coroutines and suspended functions by simply adding the “co” suffix for all functions:
class EightTest {
private val one: EightOne = mockk()
private val two: EightTwo = mockk()
private val eight = Eight(one, two)
@Test
fun `should return 1 codersee`() = runTest {
coEvery { one.returnInt() } returns 1
coEvery { two.returnString() } returns «codersee»
val result = eight.funToTest()
assertEquals(«1 codersee», result)
coVerifySequence {
one.returnInt()
two.returnString()
}
}
}
And yes, this is that easy!
MockK comes with plenty of functions to work with suspend functions, like:
coVerify
coEvery
coJustRun
coJustAwait
coAnswers
and many more
Issue With Spies
Lastly, at the moment of writing, there is one issue with spies and coroutines in MockK. You can see all the details here: https://github.com/mockk/mockk/issues/554
Assuming this is quite an old one, I wouldn’t expect it to be fixed in the near future.
But if that is the case, then please let me know in the comments below.
Summary
That’s all for this series about MockK – the mocking library for Kotlin.
During our time together, we learned A LOT, and I believe you are ready to use it in your projects!
Let me know your thoughts in the comments below, and if you are looking for the other articles, then here you are:
Getting Started with MockK in Kotlin [1/5]
MockK: Objects, Top-Level, and Extension Functions [3/5]
MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]
MockK with Coroutines [5/5]
The post MockK with Coroutines [5/5] appeared first on Codersee — Kotlin on the backend.