You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It looks like coAnswers doesn't play well with suspend lambda arguments on the mocked method. Here's an example:
classFooTest {
classFoo {
fundoSomething(block:suspend () ->Unit) {
// here I could launch a coroutine and call block()
}
}
@Test
funreproduce() {
val fooMock:Foo= mockk {
every { doSomething(captureLambda()) } coAnswers {
lambda<suspend () ->Unit>().captured.invoke()
}
}
fooMock.doSomething { }
}
}
I'm surprised that I can chain coAnswers {} after every {} (should it be available just for coEvery {}?). By doing this, it's not clear what coroutine the answer scope is expected to start on. I'm assuming it is relying on the mocked method to be suspendable and then run the answer scope in the same coroutine of the caller of the mocked method, but in this case the mocked method is not suspending at all.
Expected Behavior
I should not get a crash, or if I'm mocking things the wrong way, it'd be great to have some compile-time safeguards or at least a clearer error rather than a NullPointerException.
Current Behavior
I'm getting a crash inside coAnswers before its answer scope is executed. Things work fine if I use answers { runBlocking {} } instead.
java.lang.NullPointerException
at kotlin.coroutines.jvm.internal.ContinuationImpl.getContext(ContinuationImpl.kt:105)
at kotlin.coroutines.jvm.internal.ContinuationImpl.<init>(ContinuationImpl.kt:102)
at kotlin.coroutines.jvm.internal.SuspendLambda.<init>(ContinuationImpl.kt:159)
at io.mockk.CoFunctionAnswer$answer$1.<init>(Answers.kt)
at io.mockk.CoFunctionAnswer$answer$1.create(Answers.kt)
at io.mockk.CoFunctionAnswer$answer$1.invoke(Answers.kt)
at io.mockk.JvmCoroutineCall.callCoroutine(InternalPlatformDsl.kt:212)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.mockk.JvmCoroutineCall.callWithContinuation(InternalPlatformDsl.kt:217)
at io.mockk.CoFunctionAnswer.answer(Answers.kt:34)
at io.mockk.impl.stub.AnswerAnsweringOpportunity.answer(AnswerAnsweringOpportunity.kt:14)
at io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:54)
at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:25)
at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:20)
at com.shopify.pos.customerview.common.internal.client.statemachine.FooTest$Foo.doSomething(FooTest.kt:12)
at com.shopify.pos.customerview.common.internal.client.statemachine.FooTest.reproduce(FooTest.kt:22)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
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.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:834)
Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
MockK version: 1.11.0
OS: macOS 11.2.3
Kotlin version: 1.4.31
JDK version: OpenJDK 1.8.0_242
JUnit version: 4.12
Type of test: unit test
The text was updated successfully, but these errors were encountered:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.
It looks like
coAnswers
doesn't play well withsuspend
lambda arguments on the mocked method. Here's an example:I'm surprised that I can chain
coAnswers {}
afterevery {}
(should it be available just forcoEvery {}
?). By doing this, it's not clear what coroutine the answer scope is expected to start on. I'm assuming it is relying on the mocked method to be suspendable and then run the answer scope in the same coroutine of the caller of the mocked method, but in this case the mocked method is not suspending at all.Expected Behavior
I should not get a crash, or if I'm mocking things the wrong way, it'd be great to have some compile-time safeguards or at least a clearer error rather than a
NullPointerException
.Current Behavior
I'm getting a crash inside
coAnswers
before its answer scope is executed. Things work fine if I useanswers { runBlocking {} }
instead.Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
The text was updated successfully, but these errors were encountered: