11

I've been migrating a project from Java 8 to Java 12. Everything went well except for unit tests. When I compile and launch tests with Maven, many tests fail with the following message:

java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
    at com.tetratech.csoft.ui.jfx.AppContextTest.<init>(AppContextTest.java:22)
Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in java.lang.CompoundEnumeration@35fd987b
Caused by: org.mockito.exceptions.base.MockitoInitializationException: 

Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)

Java               : 12
JVM vendor name    : Oracle Corporation
JVM vendor version : 12+33
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 12+33
JVM info           : mixed mode, sharing
OS name            : Windows 10
OS version         : 10.0

Caused by: java.lang.IllegalStateException: Could not self-attach to current VM using external process

When lauched from IntelliJ, I get a more detailed message:

java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)

    at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:74)
    at com.sun.proxy.$Proxy7.isTypeMockable(Unknown Source)
    at org.mockito.internal.util.MockUtil.typeMockabilityOf(MockUtil.java:29)
    at org.mockito.internal.util.MockCreationValidator.validateType(MockCreationValidator.java:22)
    at org.mockito.internal.creation.MockSettingsImpl.validatedSettings(MockSettingsImpl.java:240)
    at org.mockito.internal.creation.MockSettingsImpl.build(MockSettingsImpl.java:228)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:61)
    at org.mockito.Mockito.mock(Mockito.java:1907)
    at org.mockito.Mockito.mock(Mockito.java:1816)
    at com.tetratech.csoft.ui.jfx.AppContextTest.<init>(AppContextTest.java:22)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    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.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in java.lang.CompoundEnumeration@460d0a57
    at org.mockito.internal.configuration.plugins.PluginInitializer.loadImpl(PluginInitializer.java:54)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:57)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:44)
    at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:22)
    at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:19)
    at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
    ... 29 more
Caused by: org.mockito.exceptions.base.MockitoInitializationException: 
Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)

Java               : 12
JVM vendor name    : Oracle Corporation
JVM vendor version : 12+33
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 12+33
JVM info           : mixed mode, sharing
OS name            : Windows 10
OS version         : 10.0

To solve this, as suggested as answers to similar problems, I modified pom.xml to include the following dependancies:

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.25.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>2.25.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy</artifactId>
            <version>1.9.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy-agent</artifactId>
            <version>1.9.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.objenesis</groupId>
            <artifactId>objenesis</artifactId>
            <version>3.0.1</version>
            <scope>test</scope>
        </dependency>

According to some people, this is the kind of problem that occurs when launching tests with a JRE instead of a JDK. Since I'm using OpenJDK 12, this is not the case.

Tests failing in OpenJDK 12 used to run successfully in Java 8. There were no modifications other than the ones I've shown you. org.mockito.plugins.MockMaker is required in our tests because many classes come from legacy code, with a lot of final classes. And as you can see in the message log, tests are launched with OpenJDK 12 running on Windows 10.

Is there any way to run these tests with Mockito? I know that PowerMockito can probably solve this problem, but using it means a lot of modifications in test classes.

Thanks.

Francois
  • 586
  • 2
  • 6
  • 19

1 Answers1

10

I've finally been able to solve my problem. The key to the answer is the line

java.lang.IllegalStateException: Could not self-attach to current VM using external process

For Java 9 and more, one must add -Djdk.attach.allowAttachSelf=true as VM argument to avoid this exception. When I did, unit tests ran perfectly.

Here are the links where I've found this :

https://github.com/raphw/byte-buddy/issues/612

https://github.com/mockk/mockk/issues/254

Francois
  • 586
  • 2
  • 6
  • 19
  • Android Studio uses Java 8 – IgorGanapolsky Jul 02 '19 at 15:18
  • @IgorGanapolsky Thanks for the information, but how does it help? As I mentioned, my tests were running with Java 12 under Windows 10. – Francois Jul 02 '19 at 19:40
  • The OP was mentioning **Android** – IgorGanapolsky Jul 02 '19 at 22:51
  • My issues is one test passes and the other fails where I am using Mockito in the same way to mock an activity. Passes tests in one and fails to run in the other.... – JPM Jul 19 '21 at 15:24
  • where should I add `-Djdk.attach.allowAttachSelf=true` – MohammadBaqer May 10 '22 at 12:51
  • 1
    @MohammadBaqer It depends...You can add it to your Java command line. In a Maven file, you may have to add someting like `-Djdk.attach.allowAttachSelf=true` as a Java property. You should have a look at the following question: https://stackoverflow.com/questions/50498102/how-to-set-jdk-attach-allowattachself-true-globally. Hope this helps. – Francois May 11 '22 at 19:26