Skip to content

Instantly share code, notes, and snippets.

@mirceanis
Created August 6, 2018 18:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirceanis/716bf019a47826564fa57a77065f2335 to your computer and use it in GitHub Desktop.
Save mirceanis/716bf019a47826564fa57a77065f2335 to your computer and use it in GitHub Desktop.
Mocking suspend functions that wrap callbacks - works as long as they're not extensions
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import kotlinx.coroutines.experimental.runBlocking
import org.junit.Assert
import org.junit.Test
import kotlin.coroutines.experimental.suspendCoroutine
/**
* Mocking suspend functions that wrap callbacks
*
* Trying to mock a suspend function works but when that function is an extension, it fails with InvalidUseOfMatchersException
*
*
* The setup for testing:
* dependencies {
* testImplementation "junit:junit:4.12"
* testImplementation "org.mockito:mockito-inline:2.19.0"
* testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.0.0-RC1"
* }
*/
class SuspendExtensionTest {
interface Foo {
/**
* a method with a callback
*/
fun doLongOperation(arg: String, callback: (Exception?, Long) -> Unit)
/**
* the suspend variant of the above method, usable in coroutines
*/
suspend fun doLongOperationSuspend(arg: String): Long = suspendCoroutine { cont ->
this.doLongOperation(arg) { err, result ->
if (err == null) {
cont.resume(result)
} else {
cont.resumeWithException(err)
}
}
}
}
/**
* the suspend variant of the callback method, added as an extension function
*/
suspend fun Foo.doLongOperationSuspendExt(arg: String): Long = suspendCoroutine { cont ->
this.doLongOperation(arg) { err, result ->
if (err == null) {
cont.resume(result)
} else {
cont.resumeWithException(err)
}
}
}
//This works
@Test
fun checkSuspendable() = runBlocking {
val foo: Foo = mock()
whenever(foo.doLongOperationSuspend(any())) doReturn 1234
val result = foo.doLongOperationSuspend("")
Assert.assertEquals(result, 1234)
}
//This does not work
@Test
fun checkSuspendableExtension() = runBlocking {
val foo: Foo = mock()
whenever(foo.doLongOperationSuspendExt(any())) doReturn 1234
val result = foo.doLongOperationSuspendExt("")
Assert.assertEquals(result, 1234)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment