Using kotlin 1.4 Mockk wraps Result answers in another Result
See original GitHub issuePrerequisites
Please answer the following questions for yourself before submitting an issue.
- [ X] I am running the latest version (1.10.0)
- [ X] I checked the documentation and found no answer
- [ X] I checked to make sure that this issue has not already been filed
Expected Behavior
if i mock a method which returns a kotlin.Result, i want mockk to return the value i gave as answer defined by the every or coEvery block
Current Behavior
if i mock a method which returns a kotlin.Result, the defined answer gets wrapped in another Result
coEvery { R.t() } returns Result.success(2) -> Success(Success(2))
Failure Information (for bugs)
used versions kotlin jvm 1.4, kotlin coroutines 1.3.9, gradle 6.6.1, kotest 4.2.0 using kotlin 1.3.71 with kotlintest 3.4.2 (now kotest) and coroutines 1.3.7 this was working as expected kotlin compiler needs the -Xallow-result-return-type parameter to allow for Result as return type
Steps to Reproduce
run test i attached
Context
- MockK version: 1.10.0
- OS: mac os 10.15.6
- Kotlin version: 1.4
- JDK version: 1.8
- JUnit version: 5.5.2
- Type of test: Unit
Failure Logs
Stack trace
// -----------------------[ YOUR STACK STARTS HERE ] -----------------------
mocked answer is Success(Success(2))
expected:<2> but was:<Success(2)>
Expected :2
Actual :Success(2)
<Click to see difference>
org.opentest4j.AssertionFailedError: expected:<2> but was:<Success(2)>
at seat.mod.testing.vehicle.factory.ib.Test$1$1.invokeSuspend(Test.kt:19)
at seat.mod.testing.vehicle.factory.ib.Test$1$1.invoke(Test.kt)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invokeSuspend(executions.kt:13)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invoke(executions.kt)
at io.kotest.core.internal.ExecutionsKt.wrapTestWithGlobalAssert(executions.kt:39)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invokeSuspend(executions.kt:12)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invoke(executions.kt)
at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invokeSuspend(executions.kt:25)
at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invoke(executions.kt)
at io.kotest.core.internal.AssertionsCheckKt.executeWithAssertionsCheck(assertionsCheck.kt:25)
at io.kotest.core.internal.ExecutionsKt.wrapTestWithAssertionModeCheck(executions.kt:24)
at io.kotest.core.internal.ExecutionsKt.executeWithBehaviours(executions.kt:11)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invokeSuspend(TestCaseExecutor.kt:207)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:194)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invokeSuspend(TestCaseExecutor.kt:201)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invoke(TestCaseExecutor.kt)
at io.kotest.mpp.ReplayKt.replay(replay.kt:18)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invokeSuspend(TestCaseExecutor.kt:196)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:120)
at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:37)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invokeSuspend(TestCaseExecutor.kt:195)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invoke(TestCaseExecutor.kt)
at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$$inlined$suspendCoroutine$lambda$2.invokeSuspend(ExecutorExecutionContext.kt:46)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotest.engine.ExecutorExecutionContext.executeWithTimeoutInterruption(ExecutorExecutionContext.kt:45)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invokeSuspend(TestCaseExecutor.kt:194)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:120)
at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:37)
at io.kotest.core.internal.TestCaseExecutor.executeAndWait(TestCaseExecutor.kt:192)
at io.kotest.core.internal.TestCaseExecutor.invokeTestCase(TestCaseExecutor.kt:161)
at io.kotest.core.internal.TestCaseExecutor.executeActiveTest(TestCaseExecutor.kt:130)
at io.kotest.core.internal.TestCaseExecutor$intercept$2.invokeSuspend(TestCaseExecutor.kt:80)
at io.kotest.core.internal.TestCaseExecutor$intercept$2.invoke(TestCaseExecutor.kt)
at io.kotest.core.internal.TestCaseExecutor.executeIfActive(TestCaseExecutor.kt:94)
at io.kotest.core.internal.TestCaseExecutor.intercept(TestCaseExecutor.kt:80)
at io.kotest.core.internal.TestCaseExecutor.execute(TestCaseExecutor.kt:61)
at io.kotest.engine.runners.SingleInstanceSpecRunner.runTest(SingleInstanceSpecRunner.kt:73)
at io.kotest.engine.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$1.invokeSuspend(SingleInstanceSpecRunner.kt:83)
at io.kotest.engine.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$1.invoke(SingleInstanceSpecRunner.kt)
at io.kotest.engine.spec.SpecRunner$runParallel$$inlined$map$lambda$2$1.invokeSuspend(SpecRunner.kt:80)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotest.engine.spec.SpecRunner$runParallel$$inlined$map$lambda$2.run(SpecRunner.kt:79)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
expected:<2> but was:<Success(2)>
Expected :2
Actual :Success(2)
<Click to see difference>
org.opentest4j.AssertionFailedError: expected:<2> but was:<Success(2)>
at seat.mod.testing.vehicle.factory.ib.Test$1$2.invokeSuspend(Test.kt:30)
at seat.mod.testing.vehicle.factory.ib.Test$1$2.invoke(Test.kt)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invokeSuspend(executions.kt:13)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invoke(executions.kt)
at io.kotest.core.internal.ExecutionsKt.wrapTestWithGlobalAssert(executions.kt:39)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invokeSuspend(executions.kt:12)
at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invoke(executions.kt)
at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invokeSuspend(executions.kt:25)
at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invoke(executions.kt)
at io.kotest.core.internal.AssertionsCheckKt.executeWithAssertionsCheck(assertionsCheck.kt:25)
at io.kotest.core.internal.ExecutionsKt.wrapTestWithAssertionModeCheck(executions.kt:24)
at io.kotest.core.internal.ExecutionsKt.executeWithBehaviours(executions.kt:11)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invokeSuspend(TestCaseExecutor.kt:207)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:194)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invokeSuspend(TestCaseExecutor.kt:201)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invoke(TestCaseExecutor.kt)
at io.kotest.mpp.ReplayKt.replay(replay.kt:18)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invokeSuspend(TestCaseExecutor.kt:196)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:120)
at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:37)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invokeSuspend(TestCaseExecutor.kt:195)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invoke(TestCaseExecutor.kt)
at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$$inlined$suspendCoroutine$lambda$2.invokeSuspend(ExecutorExecutionContext.kt:46)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotest.engine.ExecutorExecutionContext.executeWithTimeoutInterruption(ExecutorExecutionContext.kt:45)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invokeSuspend(TestCaseExecutor.kt:194)
at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invoke(TestCaseExecutor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:120)
at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:37)
at io.kotest.core.internal.TestCaseExecutor.executeAndWait(TestCaseExecutor.kt:192)
at io.kotest.core.internal.TestCaseExecutor.invokeTestCase(TestCaseExecutor.kt:161)
at io.kotest.core.internal.TestCaseExecutor.executeActiveTest(TestCaseExecutor.kt:130)
at io.kotest.core.internal.TestCaseExecutor$intercept$2.invokeSuspend(TestCaseExecutor.kt:80)
at io.kotest.core.internal.TestCaseExecutor$intercept$2.invoke(TestCaseExecutor.kt)
at io.kotest.core.internal.TestCaseExecutor.executeIfActive(TestCaseExecutor.kt:94)
at io.kotest.core.internal.TestCaseExecutor.intercept(TestCaseExecutor.kt:80)
at io.kotest.core.internal.TestCaseExecutor.execute(TestCaseExecutor.kt:61)
at io.kotest.engine.runners.SingleInstanceSpecRunner.runTest(SingleInstanceSpecRunner.kt:73)
at io.kotest.engine.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$1.invokeSuspend(SingleInstanceSpecRunner.kt:83)
at io.kotest.engine.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$1.invoke(SingleInstanceSpecRunner.kt)
at io.kotest.engine.spec.SpecRunner$runParallel$$inlined$map$lambda$2$1.invokeSuspend(SpecRunner.kt:80)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at io.kotest.engine.spec.SpecRunner$runParallel$$inlined$map$lambda$2.run(SpecRunner.kt:79)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
mocked answer is Success(Success(2))
Minimal reproducible code (the gist of this issue)
// -----------------------[ GRADLE DEFINITIONS ] -----------------------
dependencies {
testImplementation 'io.kotest:kotest-runner-junit5-jvm:4.2.0'
testImplementation 'io.kotest:kotest-assertions-core-jvm:4.20'
testImplementation 'io.mockk:mockk:1.10.0'
}
tasks.withType<KotlinCompile> {
kotlinOptions {
apiVersion = "1.4"
languageVersion = "1.4"
jvmTarget = "1.8"
freeCompilerArgs += "-progressive"
freeCompilerArgs += "-Xjsr305=strict"
freeCompilerArgs += "-Xallow-result-return-type"
}
}
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
import io.kotest.core.spec.style.FreeSpec
import io.kotest.matchers.shouldBe
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockkObject
internal class Test : FreeSpec({
"R.t()answer of type Result gets wrapped in Result" {
mockkObject(R)
coEvery { R.t() } returns Result.success(2)
val answer = R.t()
println("mocked answer is $answer")
answer.getOrThrow() shouldBe 2
}
"T.t()answer of type Result gets wrapped in Result" {
mockkObject(T)
every { T.t() } returns Result.success(2)
val answer = T.t()
println("mocked answer is $answer")
answer.getOrThrow() shouldBe 2
}
})
object R {
suspend fun t() = Result.success(1)
}
object T {
fun t() = Result.success(1)
}
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
Issue Analytics
- State:
- Created 3 years ago
- Comments:6
Top Results From Across the Web
MockK | mocking library for Kotlin
Provides DSL to mock behavior. Built from zero to fit Kotlin language. Supports named parameters, object mocks, coroutines and extension function mocking.
Read more >Problems with Kotlin Result<T> on unit tests
The problem is, somehow the value of the Result object is wrapped by another Result , and we can pull the desired value...
Read more >Testing Kotlin Lambda Invocations without Mocking
Mocking is a common way to help verify that the code under test has (or has not) interacted with a dependency. We can...
Read more >Create more complicated answers for stubs | MockK Guidebook
Using answers when returns just isn't enough. ... If you want to change the result of a mocked method depending on its arguments,...
Read more >Table of Contents - Micronaut Documentation
With 3.4.0, you can reference other beans properties in @Requires to load ... The way the server binds to random ports has improved...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I think #633 could potentially fix this.
Any ETA on this? Is there a workaround? This is a pretty bad bug imho.