Reputation: 336
I have the following kotlin suspending function:
suspend fun registerNewTransaction(transaction: String): String
I am trying to test it through Spock, but I have not found the way to call this kotlin suspending function without specifying the Continuation<? super String>
parameter since Groovy identifies the kotlin container class as Java class.
I would like to know if it is possible to call suspending functions from another JVM-based language, otherwise I will have to use another testing library like JUnit.
Upvotes: 2
Views: 2158
Reputation: 1668
I used this question as a reference Call Kotlin suspend function in Java class and added this function in my code
fun <T> await(block: suspend () -> T): T =
GlobalScope.future { block.invoke() }.get()
and use it this way:
await {
myService.mySuspendedFunction(myArguments, it)
}
where it
is a kotlin.coroutines.Continuation
object
Upvotes: 0
Reputation: 1482
The answer by @julianwki will break once running something like: withContext(Dispatchers.IO) { /* ... /*/ }
A more robust version is to run with an actual CoroutineContext
rather than mocking it:
def continuation = Mock(Continuation) {
getContext() >> Dispatchers.Default
}
I assume it is somehow possible to create a Continuation
through calling TestScopeKt.TestScope(EmptyCoroutineContext.INSTANCE)
(org.jetbrains.kotlinx:kotlinx-coroutines-test
), since that seems to be what what the underlying runTest
is using. However, I newer found a good way to reach that point.
Also be aware that mocking Continuation
we do not have an implementation for fun resumeWith(result: Result<T>)
which so far does not seem to be an issue, but might be in the future. Finding a completely non-mocked solution is probably desirable.
Additionally, if calling a suspend function from Groovy/Spock one might be out of luck. I did try the solutions suggested on: Call Kotlin suspend function in Java class and similar "hacks" without any luck, if calling them directly from Groovy. One might be able to make a Kotlin wrapper for each single call needed, however, in my case at least it is not viable
Upvotes: 1
Reputation: 422
You can mock that Continuation object, which kotlin is compiling into the method call. This code worked for me:
// mocked continuation
def continuation = Mock(Continuation) {
getContext() >> Mock(CoroutineContext)
}
// method call which should be tested
subjectUnderTest.suspendableMethod(someParameter, continuation)
Upvotes: 4
Reputation: 3069
if it is possible to call suspending functions from another JVM-based language
It's possible, but you need to pass Continuation
as last parameter, since it's how Kotlin compiles suspend
functions
I'd suggest using Kotlin for testing Kotlin code, there are a lot of Kotlin-specific libraries like mockk
that support coroutines.
Upvotes: 0