s1monw1 opened SPR-17128 and commented

I was trying to mock a non-final, non-private Kotlin class with a simple Mockito.mock() call and got the following exception. Turns out, the problem is an embedded member extension function in combination with Spring's Service annotation. See below for an example.

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class XYService


Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.

Java : 1.8
JVM vendor name : Oracle Corporation
JVM vendor version : 25.181-b13
JVM name : Java HotSpot(TM) 64-Bit Server VM
JVM version : 1.8.0_181-b13
JVM info : mixed mode
OS name : Mac OS X
OS version : 10.13.6

Underlying exception : java.lang.IllegalArgumentException: object is not an instance of declaring class

at XYTest.mockTest(AnotherServiceTests.kt:45)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
 at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
 at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
 at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
 at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
 at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
 at java.util.Iterator.forEachRemaining(Iterator.java:116)
 at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
 at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
 at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
 at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
 at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
 at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
 at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
 at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
 at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
 at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
 at java.util.Iterator.forEachRemaining(Iterator.java:116)
 at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
 at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
 at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
 at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
 at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
 at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
 at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
 at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
 at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
 at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
 at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
 at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeArgument.resolve(TypeDescription.java:3210)
 at net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$Chained.resolve(TypeDescription.java:2995)
 at net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeArgument.resolve(TypeDescription.java:3183)
 at net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator.asList(TypeDescription.java:2949)
 at net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$ForLoadedType.getDeclaredAnnotations(TypeDescription.java:4164)
 at net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$Latent.getDeclaredAnnotations(TypeDescription.java:4319)
 at net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$Latent.getDeclaredAnnotations(TypeDescription.java:4319)
 at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.apply(AnnotationAppender.java:639)
 at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onWildcard(AnnotationAppender.java:582)
 at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onWildcard(AnnotationAppender.java:333)
 at net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType.accept(TypeDescription.java:4072)
 at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onParameterizedType(AnnotationAppender.java:601)
 at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onParameterizedType(AnnotationAppender.java:333)
 at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType.accept(TypeDescription.java:4429)
 at net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod.apply(MethodAttributeAppender.java:183)
 at net.bytebuddy.implementation.attribute.MethodAttributeAppender$Compound.apply(MethodAttributeAppender.java:425)
 at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyAttributes(TypeWriter.java:615)
 at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:607)
 at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:526)
 at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:4170)
 at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
 at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:174)
 at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
 at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2639)
 at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2741)
 at org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator.mockClass(SubclassBytecodeGenerator.java:120)
 at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:37)
 at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:34)
 at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
 at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:346)
 at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:161)
 at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:355)
 at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:32)
 at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMockType(SubclassByteBuddyMockMaker.java:71)
 at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:42)
 at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:25)
 at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
 at org.mockito.internal.MockitoCore.mock(MockitoCore.java:65)
 at org.mockito.Mockito.mock(Mockito.java:1855)
 at org.mockito.Mockito.mock(Mockito.java:1768)
 ... 55 more

Reproduce it with this simple Test:

 @Service
 class TestClass {
 fun <T> List<T>.x() = "x"
 }

 @Test
 fun mockTest() {
 Mockito.mock(TestClass::class.java)
 }

Two ways to make it work: 1) Remove @Service and make the class open or 2) Remove the generics from the member extension method, e.g. fun String.x = "x"

Thanks in advance.

kotlin: '1.2.51' springBoot: '2.0.3.RELEASE'


Affects: 5.0.7

1 votes, 4 watchers

Comment From: sdeleuze

Hi, sorry for the delay.

Does not look like a Spring issue, I would recommand to use Mockk which is probably more suitable to handle this kind of Kotlin-specific use case (see related documentation in https://spring.io/guides/tutorials/spring-boot-kotlin/) or to create a related Mockito issue.