question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using kotlin 1.4 Mockk wraps Result answers in another Result

See original GitHub issue

Prerequisites

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

Test Results - Test.html.zip

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:open
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

2reactions
Raibazcommented, Jun 16, 2021

I think #633 could potentially fix this.

0reactions
UlfHesselbarthcommented, Jun 16, 2021

Any ETA on this? Is there a workaround? This is a pretty bad bug imho.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found