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.

Mockito 2 cannot mock kohsuke/github-api classes

See original GitHub issue

A user (Adam) on the mailing list wasn’t sure if he misused mockito. So he reached us via the mailing-list.

Hi guys, a super simple test that creates a new mock of a public non-final class org.kohsuke.github.GHIssue from https://github.com/kohsuke/github-api version 1.77, source https://github.com/kohsuke/github-api/blob/github-api-1.77/src/main/java/org/kohsuke/github/GHIssue.java fails with:

mock(GHIssue.class);
org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class org.kohsuke.github.GHIssue.

Mockito can only 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.101-b13
JVM name           : Java HotSpot(TM) 64-Bit Server VM
JVM version        : 1.8.0_101-b13
JVM info           : mixed mode
OS name            : Mac OS X
OS version         : 10.11.6


Underlying exception : java.lang.IllegalArgumentException: Cannot cast to primitive type: void

    at com.siemion.mockito.AppTest.test(AppTest.java:12)
    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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.IllegalArgumentException: Cannot cast to primitive type: void
    at net.bytebuddy.implementation.bytecode.assign.TypeCasting.to(TypeCasting.java:39)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$AccessBridgeWrapper.apply(TypeWriter.java:1100)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:3802)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1618)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:172)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:153)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2568)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2670)
    at org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator.mockClass(SubclassBytecodeGenerator.java:80)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$CachedBytecodeGenerator.getOrGenerateMockClass(TypeCachingBytecodeGenerator.java:87)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:34)
    at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMockType(SubclassByteBuddyMockMaker.java:64)
    at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:35)
    at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:22)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:63)
    at org.mockito.Mockito.mock(Mockito.java:1629)
    at org.mockito.Mockito.mock(Mockito.java:1542)
    ... 27 more

Or

mock(GHRepository.class);
java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/kohsuke/github/GHRepository$MockitoMock$667330966.getId()Ljava/lang/String; @4: checkcast
  Reason:
    Type integer (current frame, stack[0]) is not assignable to 'java/lang/Object'
  Current Frame:
    bci: @4
    flags: { }
    locals: { 'org/kohsuke/github/GHRepository$MockitoMock$667330966' }
    stack: { integer }
  Bytecode:
    0x0000000: 2ab6 003d c000 2eb0                    


    at sun.reflect.GeneratedSerializationConstructorAccessor1.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:45)
    at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
    at org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:14)

Related classes declaration

    <dependency>
      <groupId>org.kohsuke</groupId>
      <artifactId>github-api</artifactId>
      <version>1.77</version>
    </dependency>

After investigation on the project created by Adam Siemon here. I’ve reproduced the issue you are seeing with mockito 2.2.3 (bb 1.4.26) and 2.2.5 (bb 1.4.33), regardless of the JDK version. It seems related to how kohsuke/github-api generates bridge method in the byte code for backward compatibility ; this seems highly unusual, it may produce valid bytecode but with unmet bytecode patterns for mockito / bytebuddy. For reference the tool is called bridge-method-injector, more on the website

The classes you are mentioning are modified by this tool :

  • GHIssues annotated by @WithBridgeMethods(void.class)
  • GHRepository that inherits GHObject which also annotated by @WithBridgeMethods(value=String.class, adapterMethod="intToString")

It works with 1.10.19 because CGLIB is far less intelligent regarding bridge methods.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
raphwcommented, Oct 18, 2016

I understand the general intend to retain backwards compatibility but this is a general problem in Java and the hack might seem intelligent in the beginning but it is really problematic and might also confuse reflection. It would work much better if it was only used for final types.

I am glad I find these things out, encountering these issues makes Byte Buddy better in the long run 😉

0reactions
bric3commented, Oct 20, 2016

no hurry 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unexpected error (Mockito can only mock non-private ... - GitHub
Hi, Since version 2.24.0 I got the error "Mockito can only mock non-private & non-final classes.". Reverting back to Mockito 2.23.4 resolves ...
Read more >
mockito/official.md at main - GitHub
Mockito 2 cannot mock kohsuke/github -api classes (#701). Remaining changes: 1. Simplified release process by hosting javadoc on javadoc.io (#709) ...
Read more >
create a little MockGitHub class for tests mocking out the ...
there's a few projects I'd really like a simple mock implementation of GitHub for easier testing. I'm fine with it being pretty basic...
Read more >
Mockito 2 - Mocking final classes under androidTest does not ...
Hello,. Default behaviour of mockito-core and mockito-android does not contain functionalities to mock final classes:
Read more >
Mocking final classes · Issue #285 · mockito/mockito-kotlin
Caused by: org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: class org.jitsi.jibri.util.OsDetector.
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