mockk icon indicating copy to clipboard operation
mockk copied to clipboard

Duplicate boxing of captured value class arguments

Open damianw opened this issue 1 year ago • 0 comments

Please answer the following questions for yourself before submitting an issue.

  • ❌ I am running the latest version (running 1.13.11, not using Kotlin 2.0.x yet)
  • ✅ I checked the documentation and found no answer
  • ✅ I checked to make sure that this issue has not already been filed

Expected Behavior

Capturing an argument value, where the parameter type is not an inline value class, should capture the value exactly as-is.

Current Behavior

Capturing an argument value, where the parameter type is not an inline value class, boxes the argument in the value class a second time.

Steps to Reproduce

Attempt to capture an argument on a function as described above. See this test for a reproducible example:

package com.sample

import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import org.junit.Test
import kotlin.test.assertEquals

class ProblematicTest {

    interface Problematic {

        fun call(value: Any)
    }

    @Test
    fun test() {
        val mock = mockk<Problematic>(relaxed = true)
        val slot = slot<Result<Int>>()
        mock.call(Result.success(5))
        verify(exactly = 1) {
            mock.call(capture(slot))
        }
        assertEquals(Result.success(5), slot.captured)
    }
}

Stack trace

java.lang.AssertionError: expected:<Success(5)> but was:<Success(Success(5))>
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.failNotEquals(Assert.java:835)
	at org.junit.Assert.assertEquals(Assert.java:120)
	at kotlin.test.junit.JUnitAsserter.assertEquals(JUnitSupport.kt:32)
	at kotlin.test.AssertionsKt__AssertionsKt.assertEquals(Assertions.kt:63)
	at kotlin.test.AssertionsKt.assertEquals(Unknown Source)
	at kotlin.test.AssertionsKt__AssertionsKt.assertEquals$default(Assertions.kt:62)
	at kotlin.test.AssertionsKt.assertEquals$default(Unknown Source)
	at com.sample.ProblematicTest.test(Test.kt:24)
	...

Workaround

To work around this problem, the captured can use a type that is not an inline value class, and cast afterward as necessary.

package com.sample

import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import org.junit.Test
import kotlin.test.assertEquals

class ProblematicTest {

    interface Problematic {

        fun call(value: Any)
    }

    @Test
    fun test() {
        val mock = mockk<Problematic>(relaxed = true)
        val slot = slot<Any>()
        mock.call(Result.success(5))
        verify(exactly = 1) {
            mock.call(capture(slot))
        }
        assertEquals(Result.success(5), slot.captured)
    }
}

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.13.11
  • Kotlin version: 1.9.24
  • JDK version: 21
  • Type of test: unit test

damianw avatar Aug 30 '24 17:08 damianw