mockk: Bug: for classes generated by Retrofit spies fail in coVerification clause on suspend functions
Expected Behavior
A verification on a suspend function of a spy object is possible.
Current Behavior
The verification fails always.
Failure Information (for bugs)
I was trying to verify a call on a suspend function belonging to a spy object, the implementation of the function is generated code by retrofit. Since version 2.6.0 retrofit allows the use of the suspend modifier. The assertion error returned is:
java.lang.AssertionError: Verification failed: call 1 of 1: $Proxy7(#1).getTest(eq(continuation {}))). Only one matching call to $Proxy7(#1)/getTest(Continuation) happened, but arguments are not matching: [0]: argument: continuation {}, matcher: eq(continuation {}), result: - 
Steps to Reproduce
- Create a spy on a retrofit service exposing an endpoint as a suspend function
- Trigger a call to said endpoint in a test
- Coverify this call
Context
- MockK version: 1.9.3
- OS: Mac OS 10.14.5
- Kotlin version: 1.3.41
- JDK version: OpenJDK 1.8.0_152-release (embedded in AS 3.4.2)
- JUnit version: 4.12
- Type of test: unit test
- Retrofit version: 2.6.1
Stacktrace
Stack trace:
                                io.mockk.impl.InternalPlatform.captureStackTrace      (InternalPlatform.kt:121)             
                                  io.mockk.impl.stub.MockKStub.handleInvocation       (MockKStub.kt:247)                    
io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation             (JvmMockFactoryHelper.kt:25)          
                         io.mockk.proxy.jvm.advice.Interceptor.call                   (Interceptor.kt:20)                   
                                         com.sun.proxy.$Proxy7.getTest                (-:-1)                                
                  com.example.myapplication.TestSubject$test$1.invokeSuspend          (TestSubject.kt:8)                    
           kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith             (ContinuationImpl.kt:33)              
                             kotlinx.coroutines.DispatchedTask.run                    (Dispatched.kt:238)                   
                          kotlinx.coroutines.EventLoopImplBase.processNextEvent       (EventLoop.kt:116)                    
                          kotlinx.coroutines.BlockingCoroutine.joinBlocking           (Builders.kt:80)                      
                     kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking            (Builders.kt:54)                      
                                 kotlinx.coroutines.BuildersKt.runBlocking            (-:1)                                 
                     kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default    (Builders.kt:36)                      
                                 kotlinx.coroutines.BuildersKt.runBlocking$default    (-:1)                                 
                         com.example.myapplication.TestSubject.test                   (TestSubject.kt:7)                    
                     com.example.myapplication.TestSubjectTest.test                   (TestSubjectTest.kt:34)               
                          sun.reflect.NativeMethodAccessorImpl.invoke0                (NativeMethodAccessorImpl.java:-2)N   
                          sun.reflect.NativeMethodAccessorImpl.invoke                 (NativeMethodAccessorImpl.java:62)    
                      sun.reflect.DelegatingMethodAccessorImpl.invoke                 (DelegatingMethodAccessorImpl.java:43)
                                      java.lang.reflect.Method.invoke                 (Method.java:498)                     
                     org.junit.runners.model.FrameworkMethod$1.runReflectiveCall      (FrameworkMethod.java:50)             
           org.junit.internal.runners.model.ReflectiveCallable.run                    (ReflectiveCallable.java:12)          
                       org.junit.runners.model.FrameworkMethod.invokeExplosively      (FrameworkMethod.java:47)             
            org.junit.internal.runners.statements.InvokeMethod.evaluate               (InvokeMethod.java:17)                
                                org.junit.runners.ParentRunner.runLeaf                (ParentRunner.java:325)               
                      org.junit.runners.BlockJUnit4ClassRunner.runChild               (BlockJUnit4ClassRunner.java:78)      
                      org.junit.runners.BlockJUnit4ClassRunner.runChild               (BlockJUnit4ClassRunner.java:57)      
                              org.junit.runners.ParentRunner$3.run                    (ParentRunner.java:290)               
                              org.junit.runners.ParentRunner$1.schedule               (ParentRunner.java:71)                
                                org.junit.runners.ParentRunner.runChildren            (ParentRunner.java:288)               
                                org.junit.runners.ParentRunner.access$000             (ParentRunner.java:58)                
                              org.junit.runners.ParentRunner$2.evaluate               (ParentRunner.java:268)               
                                org.junit.runners.ParentRunner.run                    (ParentRunner.java:363)               
                                    org.junit.runner.JUnitCore.run                    (JUnitCore.java:137)                  
                      com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs    (JUnit4IdeaTestRunner.java:68)        
       com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs    (IdeaTestRunner.java:47)              
                  com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart (JUnitStarter.java:242)               
                  com.intellij.rt.execution.junit.JUnitStarter.main                   (JUnitStarter.java:70)                 (timeout = 5000 ms)
	at io.mockk.impl.recording.states.VerifyingState.failIfNotPassed(VerifyingState.kt:66)
	at io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:42)
	at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:60)
	at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
	at io.mockk.MockKDsl.internalCoVerify(API.kt:143)
	at io.mockk.MockKKt.coVerify(MockK.kt:162)
	at io.mockk.MockKKt.coVerify$default(MockK.kt:159)
	at com.example.myapplication.TestSubjectTest.test(TestSubjectTest.kt:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Minimal reproducible code (the gist of this issue)
package com.example.myapplication
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import okhttp3.OkHttpClient
import org.junit.Test
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class TestSubjectTest {
    val okhttp = OkHttpClient.Builder().build()
    val testApi = spyk(Retrofit.Builder()  // THIS DOES NOT WORK
        .baseUrl("https://jsonplaceholder.typicode.com")
        .addConverterFactory(GsonConverterFactory.create())
        .client(okhttp).build().create(TestApi::class.java))
//    val testApi: TestApi = mockk {   // THIS WORKS
//        coEvery { getTest() } returns Dto(1, 1, "", false)
//    }
    val testSubject = TestSubject(testApi)
    @Test
    fun test() {
        testSubject.test()
        coVerify { testApi.getTest() }
    }
}
package com.example.myapplication
import retrofit2.http.GET
interface TestApi {
    @GET("/todos/1")
    suspend fun getTest(): Dto
}
data class Dto(val userId: Int, val id: Int, val title: String, val completed: Boolean)
package com.example.myapplication
import kotlinx.coroutines.runBlocking
class TestSubject(private val testApi: TestApi) {
    fun test() {
        runBlocking {
            testApi.getTest()
        }
    }
}
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 5
- Comments: 25 (1 by maintainers)
Hi folks, we build a solution based on @palatin example.
Usage:
We also have to create functions for the amount of parameters that we required.
@DevSrSouza Iām not able to find
KSuspendFunction1, what Kotlin version are you using?Mine is
1.4.31The simplest MWE tests that fail with:
Stacktraces: