Skip to content

Mocking methods returning nullable value classes enters an infinite loop #656

@schernetsky

Description

@schernetsky

Expected Behavior

Mocking methods returning nullable value classes does not cause an infinite loop.

Current Behavior

Mocking methods returning nullable value classes causes an infinite loop.

Failure Information (for bugs)

The infinite loop happens within the every block

Steps to Reproduce

Mock a method returning a nullable value class

Context

  • MockK version: 1.12.0
  • OS: OSX 10.14.6
  • Kotlin version: 1.5.10
  • JDK version: 11
  • JUnit version: 4.12
  • Type of test: unit test

Stack trace

From debugger:

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
	  at java.lang.Throwable.fillInStackTrace(Throwable.java:-1)
	  at java.lang.Throwable.fillInStackTrace(Throwable.java:787)
	  - locked <0xfab> (a java.lang.Exception)
	  at java.lang.Throwable.<init>(Throwable.java:270)
	  at java.lang.Exception.<init>(Exception.java:66)
	  at io.mockk.impl.InternalPlatform.captureStackTrace(InternalPlatform.kt:124)
	  at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:250)
	  at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:23)
	  at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:21)
	  at test.NullableValueClassTest$DummyValue.getValue(NullableValueClassTest.kt:18)
	  at jdk.internal.reflect.GeneratedMethodAccessor7.invoke(Unknown Source:-1)
	  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	  at java.lang.reflect.Method.invoke(Method.java:566)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
	  at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.call(InlineClassAwareCaller.kt:135)
	  at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
	  at kotlin.reflect.jvm.internal.KProperty1Impl.get(KProperty1Impl.kt:35)
          ...
	  at io.mockk.ValueClassSupportKt.boxedValue(ValueClassSupport.kt:24)
	  at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
	  at test.NullableValueClassTest$DummyValue.getValue(NullableValueClassTest.kt:18)
	  at jdk.internal.reflect.GeneratedMethodAccessor7.invoke(Unknown Source:-1)
	  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	  at java.lang.reflect.Method.invoke(Method.java:566)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
	  at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.call(InlineClassAwareCaller.kt:135)
	  at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
	  at kotlin.reflect.jvm.internal.KProperty1Impl.get(KProperty1Impl.kt:35)
	  at io.mockk.ValueClassSupportKt.boxedValue(ValueClassSupport.kt:24)
	  at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
	  at test.NullableValueClassTest$DummyValue.getValue(NullableValueClassTest.kt:18)
	  at jdk.internal.reflect.GeneratedMethodAccessor7.invoke(Unknown Source:-1)
	  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	  at java.lang.reflect.Method.invoke(Method.java:566)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
	  at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.call(InlineClassAwareCaller.kt:135)
	  at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
	  at kotlin.reflect.jvm.internal.KProperty1Impl.get(KProperty1Impl.kt:35)
	  at io.mockk.ValueClassSupportKt.boxedValue(ValueClassSupport.kt:24)
	  at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
	  at test.NullableValueClassTest$DummyValue.getValue(NullableValueClassTest.kt:18)
	  at jdk.internal.reflect.GeneratedMethodAccessor7.invoke(Unknown Source:-1)
	  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	  at java.lang.reflect.Method.invoke(Method.java:566)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
	  at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
	  at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.call(InlineClassAwareCaller.kt:135)
	  at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
	  at kotlin.reflect.jvm.internal.KProperty1Impl.get(KProperty1Impl.kt:35)
	  at io.mockk.ValueClassSupportKt.boxedValue(ValueClassSupport.kt:24)
	  at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
	  at io.mockk.proxy.jvm.advice.BaseAdvice.handle(BaseAdvice.kt:42)
	  at io.mockk.proxy.jvm.advice.jvm.JvmMockKProxyInterceptor.interceptNoSuper(JvmMockKProxyInterceptor.java:45)
	  at test.NullableValueClassTest$DummyService$Subclass0.getNullableValue-EG2zCSQ(Unknown Source:-1)
	  at test.NullableValueClassTest$testNullableValueClass$mock$1$1.invoke-aFUiSyE-aFUiSyE(NullableValueClassTest.kt:13)
	  at test.NullableValueClassTest$testNullableValueClass$mock$1$1.invoke(NullableValueClassTest.kt:13)
	  at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
	  at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:78)
	  at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
	  at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:40)
	  at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
	  at io.mockk.MockKDsl.internalEvery(API.kt:92)
	  at io.mockk.MockKKt.every(MockK.kt:98)
	  at test.NullableValueClassTest.testNullableValueClass(NullableValueClassTest.kt:13)

Minimal reproducible code (the gist of this issue)

package test

import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Test

class NullableValueClassTest {

    @Test
    fun testNullableValueClass() {
        val expectedValue = DummyValue(0)
        val mock = mockk<DummyService> { every { getNullableValue() } returns expectedValue }
        assertEquals(expectedValue, mock.getNullableValue())
    }

    @JvmInline
    value class DummyValue(val value: Int)

    interface DummyService {
        fun getNullableValue(): DummyValue?
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions