David Kubecka
12/08/2022, 11:12 AMinterface AProvider {
context(ContextProvider)
fun getA(a: String) = a
}
class ContextProvider
inline fun <reified T : Any> mockkWithContext(noinline block: context(ContextProvider) T.() -> Unit) =
withContext { mockk<T> { block(this@withContext, this@mockk) } }
fun <T> withContext(block: ContextProvider.() -> T) = ContextProvider().block()
class ContextReceiversTest {
@Test
fun `a test`() {
val aProviderMock: AProvider = mockkWithContext {
every { getA(any()) } answers { firstArg() }
}
println(withContext { aProviderMock.getA("a") })
}
}
As you can see the getA method has ContextProvider
as a receiver. In order to mock it in the test I have to wrap standard mockk
in withContext
which provides the required receiver for getA
. If I run the test, though, it fails on
io.mockk.MockKException: no answer found for: AProvider(#1).getA(com.example.playground.ContextProvider@38b5f25, a)
Apparently mockk expects the receiver as the first argument but obviously I cannot write every { getA(any(), any()) }
. So my question is how can I mock the method in my case?Adam S
12/08/2022, 1:25 PMsuspend fun
works, and MockK provides specific functions for mocking those. Supporting context receivers will probably be similar.
I wonder, what happens if you try coEvery { getA(any()) }
?
If you need something that works right now, then you could try manually mock by creating an object that implements AProvider
fun mockAProvider() = object : AProvider {
context(ContextProvider)
override fun getA(a: String) = "stubbed response"
}
David Kubecka
12/08/2022, 2:17 PMcoEvery
doesn't work and the object workaround is probably applicable only in simple cases (not what I have in reality). I didn't see context-receivers related MockK issue so I will file one.David Kubecka
12/08/2022, 2:25 PM