Closed chris-horner closed 4 years ago
I'm facing the same issue and created a test for it in my fork. I'm still investigating it to figure out what is happening
I'm facing the same issue here and can not mock anything with coroutines. I think MockRetrofit is not updated to work with coroutines like Retrofit...
Yep this needs to be special-cased the same way it was inside regular Retrofit.
Should be great to add the Retrofit.create()
extension to MockRetrofit too.
@JakeWharton is there any place to check the advances in this issue? Maybe some sonatype snapshot?
Updates will occur on this issue. For now, it remains a bug.
On Sun, Sep 15, 2019, 7:43 PM Javier Segovia Córdoba < notifications@github.com> wrote:
@JakeWharton https://github.com/JakeWharton is there any place to check the advances in this issue? Maybe some sonatype snapshot?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/square/retrofit/issues/3148?email_source=notifications&email_token=AAAQIEIO3ATGAU6HQKMSPTDQJ3CDXA5CNFSM4H6KDRIKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6X3QSA#issuecomment-531609672, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQIEJZF3X6KQUMWVTQSGTQJ3CDXANCNFSM4H6KDRIA .
Have same issue for regular retrofit without any retrofit-mock's
@GET("url")
suspend fun getClient(@Header("email") email: String): ClientPayload
for method Api.getClient
at retrofit2.Utils.methodError(Utils.java:52)
at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:105)
at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:66)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:37)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
at java.lang.reflect.Proxy.invoke(Proxy.java:397)
at $Proxy0.getClient(Unknown Source)
at com..android.data.ClientRegistrationRepository.getClient(ClientRegistrationRepository.kt:23)
at com..android.domain.client.ClientNameUseCase$updateClientNameSettings$2.invokeSuspend(ClientNameUseCase.kt:21)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class java.lang.Object.
Tried:
* retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
* retrofit2.DefaultCallAdapterFactory
at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:241)
at retrofit2.Retrofit.callAdapter(Retrofit.java:205)
at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:103)
... 13 more
I am having the same problem as well without retrofit-mock.
@GET("url")
suspend fun getItem(): SomeResponse
java.lang.IllegalArgumentException: Unable to create call adapter for class java.lang.Object
for method SomeService.getItem
at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:755)
at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:240)
at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:165)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy3.getItem(Unknown Source)
at ...
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:186)
at ...
at ...
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.ResumeModeKt.resumeUninterceptedMode(ResumeMode.kt:45)
at kotlinx.coroutines.internal.ScopeCoroutine.onCompletionInternal$kotlinx_coroutines_core(Scopes.kt:28)
at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:305)
at kotlinx.coroutines.JobSupport.tryFinalizeFinishingState(JobSupport.kt:230)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:799)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:742)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:117)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class java.lang.Object.
Tried:
* com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
* retrofit2.ExecutorCallAdapterFactory
at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:241)
at retrofit2.Retrofit.callAdapter(Retrofit.java:205)
at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:238)
... 28 more
I was able to reproduce this bug on the latest version of Retrofit (v2.6.2) while I was testing the latest support for coroutines. It would be great to have mock responses working, too.
I'm playing a bit with Retrofit code to implement a fix, but some code related to suspend functions support is package private in Retrofit. @JakeWharton is someone working on a fix? What would be an acceptable solution for this?
No one is working on it. Feel free to add support and send a PR!
On Sat, Oct 26, 2019, 2:31 PM Rafael Toledo notifications@github.com wrote:
I'm playing a bit with Retrofit code to implement a fix, but some code related to suspend functions support is package private in Retrofit. @JakeWharton https://github.com/JakeWharton is someone working on a fix? What would be an acceptable solution for this?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/square/retrofit/issues/3148?email_source=notifications&email_token=AAAQIELQAXFG5WGD4RBESE3QQSEJBA5CNFSM4H6KDRIKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECKOEIQ#issuecomment-546628130, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAQIEJ4HUEDQGIBDNZK6RTQQSEJBANCNFSM4H6KDRIA .
@rafaeltoledo We have the blessing. It's up to us. Show me what you've got!
I took a look at the logs and I believe I have found the root cause and special casing that Jake mentioned earlier.
It looks like in HttpServiceMethod
we check for requestFactory.isKotlinSuspensionFunction
to determine which adapterType
to use; i.e. the coroutine Response Type or a Generic Return Type.
The adapterType
is then used by a private method called createCallAdapter()
to return an adapter appropriate for a couroutine Response or a Generic Response.
In the Mock Retrofit BehaviorDelegate
, we naively use the Generic Response Type to create a Call Adapter which is why everyone sees java.lang.IllegalArgumentException: Could not locate call adapter for class java.lang.Object
in their logs.
Rather than expose the private method for createCallAdapter
, can we think of a reason why the requestFactory.isKotlinSuspensionFunction
is not being hit or cannot be used by Mock Retrofit? This is where someone else's knowledge of the library will come in handy.
@vrickey123 I'm not too familiar with Retrofit-Mock internals too. But I did some experiments, and now my current state is the test failing with java.lang.ClassCastException: class retrofit2.mock.BehaviorCall cannot be cast to class java.lang.String (retrofit2.mock.BehaviorCall is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
. You can check the master branch of my fork.
retrofit-mock's
BehaviorDelegate
throws an exception when attempting to return for a suspend function.For example
will throw when attempting to use:
I'd submit a failing test for this, but it would involve me pulling in Kotlin into the retrofit-mock module which I'm not sure is desirable?
Exception thrown looks like: