Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when mocking a method object is being instantiated and method is called #1186

Open
andrzej-talarek opened this issue Nov 24, 2023 · 0 comments

Comments

@andrzej-talarek
Copy link

Expected Behavior

When class we would like to mock has private function with generics that is object, class should be mocked correctly.

Current Behavior

Instead of mocking, class in instantiated and method is called - resulting in NPE if we have any private fields set in constructor.

Failure Information (for bugs)

if method (notEvenCalledAnywhere) is not private, everything works fine.

Steps to Reproduce

Declare class that has private method returning object with generics.

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.8
  • OS: Ubuntu 22.04
  • Kotlin version: 1.9.20
  • JDK version: GraalVM 20.0.2
  • JUnit version: 5.10.1
  • Type of test: unit test

Failure Logs

2023-11-24 17:24:16.554 [pool-1-thread-1]  WARN  i.m.p.j.t.InliningClassTransformer - Failed to transform class testing/SomeClass
java.lang.reflect.MalformedParameterizedTypeException: Mismatch of count of formal and actual type arguments in constructor of composite_enrichment.services.SomeClass$notEvenCalledAnywhere$1: 0 formal argument(s) 1 actual argument(s)
	at java.base/sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(ParameterizedTypeImpl.java:59)
	at java.base/sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(ParameterizedTypeImpl.java:52)
	at java.base/sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(ParameterizedTypeImpl.java:100)
	at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(CoreReflectionFactory.java:105)
	at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:140)
	at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
	at java.base/sun.reflect.generics.repository.MethodRepository.computeReturnType(MethodRepository.java:75)
	at java.base/sun.reflect.generics.repository.MethodRepository.getReturnType(MethodRepository.java:66)
	at java.base/java.lang.reflect.Method.getGenericReturnType(Method.java:297)
	at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedReturnType.resolve(TypeDescription.java:6723)
	at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection.accept(TypeDescription.java:6297)
	at net.bytebuddy.description.method.MethodDescription$AbstractBase.asToken(MethodDescription.java:891)
	at net.bytebuddy.description.method.MethodDescription$AbstractBase.asToken(MethodDescription.java:447)
	at net.bytebuddy.description.method.MethodList$AbstractBase.asTokenList(MethodList.java:90)
	at net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$1.represent(InstrumentedType.java:438)
	at net.bytebuddy.ByteBuddy.redefine(ByteBuddy.java:886)
	at net.bytebuddy.ByteBuddy.redefine(ByteBuddy.java:861)
	at io.mockk.proxy.jvm.transformation.InliningClassTransformer.transform(InliningClassTransformer.kt:74)

Stack trace

Cannot invoke "String.length()" because "this.something" is null
java.lang.NullPointerException: Cannot invoke "String.length()" because "this.something" is null
at testing.SomeClass.highFive(FailedKotestTest.kt:19)
at testing.FailedMockkingTest$1$1$tester$1$1.invoke(FailedKotestTest.kt:25)
at testing.FailedMockkingTest$1$1$tester$1$1.invoke(FailedKotestTest.kt:25)
at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:24)
at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:76)
at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:39)
at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalEvery(API.kt:94)
at io.mockk.MockKKt.every(MockK.kt:143)
at testing.FailedMockkingTest$1$1.invokeSuspend(FailedKotestTest.kt:25)```

Minimal reproducible code (the gist of this issue)

// -----------------------[ GRADLE DEFINITIONS ] -----------------------
dependencies {
    testImplementation("io.kotest:kotest-runner-junit5:5.8.0")
    testImplementation("io.kotest:kotest-assertions-core:5.8.0")
    testImplementation("io.mockk:mockk:1.13.8")
}
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
package testing

import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk

interface SomeInterface<T> {
    fun bleh(a: T): String
}

class SomeClass(private val something: String) {
    private fun <T> notEvenCalledAnywhere(a: List<T>) = object : SomeInterface<T> {
        override fun bleh(a: T): String {
            TODO("bleh not yet implemented")
        }
    }

    fun highFive(): Int = something.length
}

class FailedMockkingTest : ShouldSpec({
    should("mock method instead of calling it") {
        val tester = mockk<SomeClass> {
            every { highFive() } returns 6
        }
        tester.highFive() shouldBe 6
    }
})
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant