将springboot版本从2.4.4升级到2.7.16后执行涉及Powermock的单元测试报如下错误:
java.lang.RuntimeException: Invoking the beforeTestMethod method on PowerMock test listener org.powermock.api.extension.listener.AnnotationEnabler@407a7f2a failed.
at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:84)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:308)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:117)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.IllegalStateException: java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:92)
at org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine.process(PowerMockitoInjectingAnnotationEngine.java:40)
at org.powermock.api.extension.listener.AnnotationEnabler.injectSpiesAndInjectToSetters(AnnotationEnabler.java:61)
at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:56)
at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:82)
... 25 more
Caused by: 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:88)
at com.sun.proxy.$Proxy5.getHandler(Unknown Source)
at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:110)
at org.mockito.internal.configuration.injection.scanner.MockScanner.isMockOrSpy(MockScanner.java:83)
at org.mockito.internal.configuration.injection.scanner.MockScanner.preparedMock(MockScanner.java:71)
at org.mockito.internal.configuration.injection.scanner.MockScanner.scan(MockScanner.java:59)
at org.mockito.internal.configuration.injection.scanner.MockScanner.addPreparedMocks(MockScanner.java:45)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectCloseableMocks(InjectingAnnotationEngine.java:112)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:90)
... 29 more
Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@20bd8be5
at org.mockito.internal.configuration.plugins.PluginInitializer.loadImpl(PluginInitializer.java:58)
at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:69)
at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:54)
at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:28)
at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:22)
at org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine.preLoadPluginLoader(PowerMockitoInjectingAnnotationEngine.java:49)
at org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine.process(PowerMockitoInjectingAnnotationEngine.java:37)
... 28 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.mockito.internal.configuration.plugins.PluginInitializer.loadImpl(PluginInitializer.java:53)
... 34 more
Caused by: java.lang.ExceptionInInitializerError
at org.mockito.Mockito.<clinit>(Mockito.java:1614)
at org.powermock.api.mockito.mockmaker.MockMakerLoader.doLoad(MockMakerLoader.java:45)
at org.powermock.api.mockito.mockmaker.MockMakerLoader.load(MockMakerLoader.java:36)
at org.powermock.api.mockito.mockmaker.PowerMockMaker.<init>(PowerMockMaker.java:36)
... 39 more
Caused by: java.lang.NullPointerException
at org.mockito.internal.configuration.plugins.Plugins.getDoNotMockEnforcer(Plugins.java:105)
at org.mockito.internal.MockitoCore.<clinit>(MockitoCore.java:77)
... 43 more
看日志是MockMaker相关的实现类或者插件无法加载。
powermock的版本不变,如下:
<!-- powermock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
对比前后版本中的junit、powermock和mockito的版本变化
junit:4.13.2 无变化
junit-jupiter-api:5.7.1 -> 5.8.2
junit-platform-commons:1.71 -> 1.8.2
powermock-api-mockito2:2.0.9 无变化
powermock-api-support:2.0.9 无变化
powermock-core:2.0.9 无变化
powermock-module-junit4:2.0.9 无变化
powermock-module-junit4-common:2.0.9 无变化
powermock-reflect:2.0.9 无变化
mockito-code:3.6.28 -> 4.5.1
mockito-junit-jupiter:3.6.28 -> 4.5.1
从上面的版本变化可以看到mockito-code为大版本升级,极有可能出现冲突,而其依赖关系为spring-boot-starter-test -> mockito-junit-jupiter -> junit-jupiter-api
所有将mockito-junit-jupiter从spring-boot-starter-test排除,在添加无冲突版本的mockito-junit-jupiter,如下:
<!-- 与powermock无冲突的mockito-junit-jupiter和mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.6.28</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.6.28</version>
</dependency>
<!-- 单元自测 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<!-- 排除和powermock冲突的mockito-junit-jupiter,否则执行powermock单元报错 -->
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</exclusion>
<!-- 排除和powermock冲突的mockito-core,否则执行powermock单元报错 -->
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
</exclusions>
</dependency>
解决版本冲突后再次执行单元测试就可以正常跑了。