At the time of writing, MockK does not support context receivers, and it probably won't until context receivers are released - so some time after Kotlin 1.9, so maybe in 2024).
(Context receivers are explicitly described as not ready for production. A stable release won't be available until after the K2 release, and the K2 beta is targeted for Kotlin 1.9, which has a planned release of December 2023.)
That said, if anyone wants to attempt support, then get stuck in! MockK is an community supported open source project that accepts PRs.
Confounding factors
However, there are two hinderances before MockK can fully support context receivers:
- Context receivers aren't finished, nor is their current implementation stable. KT-10468. Their implementation could change significantly. Trying to implement support for a moving target is challenging.
- IDE support is limited, which makes developing with them difficult (follow KTIJ-20857 for updates)
Workaround
In the meantime, you could adjust your code to allow for manual mocking.
First, adjust MyClass
to either be an open class, or introduce a new interface that describes the behaviour you want to mock (code to an interface).
/** Describe the API that [MyClass] will implement */
interface MyClassSpec {
context(CallContext)
fun myMethod(a: Int): Int
}
And then implement the interface
/** Concrete implementation of [MyClassSpec] */
class MyClass: MyClassSpec {
context(CallContext)
override fun myMethod(a: Int): Int = a
}
Now in your test you can create a mock by creating an anonymous object that implements MyClassSpec
- and now you have a mock that supports context receivers.
@Test
fun myTest() {
val myClassMock = object : MyClassSpec {
context(CallContext)
override fun myMethod(a: Int): Int = 123
}
}