EasyMock conflicting with coroutines; impossible to test `suspend` in interfaces?


#1

Hi,

If I have code that looks like this, with junit 4.12, Kotlin 1.2.0, and the 0.21 coroutine packages:

interface Interface {
    suspend fun foo(): String
}

class Caller(private val instance: Interface) {
    fun execute() {
        runBlocking {
            instance.foo()
        }
    }
}

@Test
fun test() {
    runBlocking {
        val mock = createMock(Interface::class.java)
        expect(mock.foo()).andReturn("bar")
        replayAll()
        Caller(mock).execute()
    }
}

Then the test fails with

java.lang.AssertionError: 
  Unexpected method call Interface.foo(kotlinx.coroutines.experimental.CoroutineScope.() -> kotlin.String):
    Interface.foo(kotlinx.coroutines.experimental.CoroutineScope.() -> kotlin.Unit): expected: 1, actual: 0

This is preventing me from actually unit testing my classes and interfaces, which is pretty frustrating. Suggestions?


#2

Should be fine with http://mockk.io


#3

@oleksiyp Could you expand your answer, how mockk.io solves this problem? Otherwise it looks like a self-promotion.


#4

Why it looks? It is a promotion 100%. But it is still an answer to a question:

interface Interface {
    suspend fun foo(): String
}

class Caller(private val instance: Interface) {
    fun execute() {
        runBlocking {
            instance.foo()
        }
    }
}


fun main(args: Array<String>) {
    runBlocking {
        val mock: Interface = mockk()
        coEvery { mock.foo() } returns "bar"
        Caller(mock).execute()
    }
}