使用 OpenJDK 12 使用 Mockito 启动 JUnit 时如何摆脱“无法初始化插件:接口 org.mockito.plugins.MockMaker”

Fra*_*ois 9 java junit unit-testing mockito

我一直在将一个项目从 Java 8 迁移到 Java 12。除了单元测试之外,一切都很顺利。当我使用 Maven 编译和启动测试时,许多测试失败并显示以下消息:

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
Run Code Online (Sandbox Code Playgroud)

从 IntelliJ 启动时,我收到一条更详细的消息:

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
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,正如对类似问题的答案所建议的那样,我进行了修改pom.xml以包含以下依赖项:

        <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>
Run Code Online (Sandbox Code Playgroud)

据一些人说,这是使用 JRE 而不是 JDK 启动测试时出现的那种问题。由于我使用的是 OpenJDK 12,因此情况并非如此。

OpenJDK 12 中失败的测试曾经在 Java 8 中成功运行。除了我向您展示的那些之外,没有其他修改。org.mockito.plugins.MockMaker在我们的测试中是必需的,因为许多类来自遗留代码,有很多最终类。正如您在消息日志中看到的那样,测试是使用在 Windows 10 上运行的 OpenJDK 12 启动的。

有什么办法可以运行这些测试Mockito吗?我知道这PowerMockito可能可以解决这个问题,但是使用它意味着在测试类中进行大量修改。

谢谢。

Fra*_*ois 7

我终于能够解决我的问题了。答案的关键是这条线

java.lang.IllegalStateException: Could not self-attach to current VM using external process
Run Code Online (Sandbox Code Playgroud)

对于 Java 9 及更高版本,必须添加-Djdk.attach.allowAttachSelf=true为 VM 参数以避免此异常。当我这样做时,单元测试运行完美。

以下是我找到的链接:

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

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