PowerMock报错详解与解决方案
PowerMock是一个强大的java测试框架,它允许开发者在测试中模拟静态方法、构造函数以及私有方法,使用PowerMock时可能会遇到各种错误和异常,本文将详细探讨PowerMock常见的报错及其解决方案,并提供相关示例和表格归纳。

常见报错及解决方案
1. ScriptEngineManager报错
报错信息:
- javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype
原因分析:
这种错误通常是由于PowerMock与JDK的Nashorn脚本引擎不兼容引起的,在使用PowerMock 2.0.2版本时尤其常见。
解决方案:
在测试类中添加@PowerMockIgnore
注解,忽略相关的脚本引擎类。

- import org.powermock.core.classloader.annotations.PowerMockIgnore;
- import org.powermock.modules.junit4.PowerMockRunner;
- import org.junit.runner.RunWith;
- @RunWith(PowerMockRunner.class)
- @PowerMockIgnore({"javax.script.*"})
- public class VendorTest {
- // ...
- }
2. NoSuchMethodError错误
报错信息:
- java.lang.NoSuchMethodError: org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress()Lorg/mockito/internal/progress/MockingProgress;
原因分析:
这个错误通常是由于Mockito和PowerMock版本不兼容引起的,使用了不匹配的Mockito版本。
解决方案:
确保使用的Mockito版本与PowerMock版本兼容,可以在Maven或Gradle中进行相应的版本配置。

Maven配置:
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermockmodulejunit4</artifactId>
- <version>2.0.2</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockitocore</artifactId>
- <version>2.23.0</version>
- <scope>test</scope>
- </dependency>
3. ClassCastException错误
报错信息:
- java.lang.ClassCastException: com.sun.crypto.provider.AESCipher$General cannot be cast to javax.crypto.CipherSpi
原因分析:
这个错误是由于类加载器不同导致的类型转换失败,PowerMock使用JavassistMockClassLoader加载类,而系统默认使用ExtClassLoader加载类,导致类型不匹配。
解决方案:
在测试类中添加@PowerMockIgnore
注解,指定忽略相关的加密类。
- import org.powermock.core.classloader.annotations.PowerMockIgnore;
- import org.powermock.modules.junit4.PowerMockRunner;
- import org.junit.runner.RunWith;
- @RunWith(PowerMockRunner.class)
- @PowerMockIgnore("javax.crypto.*")
- public class AESUtilTest {
- // ...
- }
4. NoClassDefFoundError错误
报错信息:
- java.lang.NoClassDefFoundError: org/junit/internal/runners/BeforeAndAfterRunner
原因分析:
这个错误通常是由于使用了错误的PowerMockRunner,JUnit 4.4及更高版本需要使用新的Runner程序,而较旧的版本则需要使用旧的Runner程序。
解决方案:
根据使用的JUnit版本选择合适的PowerMockRunner,对于JUnit 4.4及更高版本,使用PowerMockRunner
;对于较旧版本,使用legacy.PowerMockRunner
。
Maven配置示例:
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermockmodulejunit4</artifactId>
- <version>2.0.2</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
报错类型 | 报错信息 | 原因分析 | 解决方案 |
ScriptEngineManager报错 | javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype | PowerMock与JDK的Nashorn脚本引擎不兼容 | 使用@PowerMockIgnore("javax.script.*") 注解 |
NoSuchMethodError错误 | java.lang.NoSuchMethodError: org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress()Lorg/mockito/internal/progress/MockingProgress; | Mockito和PowerMock版本不兼容 | 确保版本匹配,如Mockito 2.23.0和PowerMock 2.0.2 |
ClassCastException错误 | java.lang.ClassCastException: com.sun.crypto.provider.AESCipher$General cannot be cast to javax.crypto.CipherSpi | 类加载器不同导致类型转换失败 | 使用@PowerMockIgnore("javax.crypto.*") 注解 |
NoClassDefFoundError错误 | java.lang.NoClassDefFoundError: org/junit/internal/runners/BeforeAndAfterRunner | 使用了错误的PowerMockRunner | 根据JUnit版本选择合适的PowerMockRunner |
FAQs
Q1: 如何在Maven项目中配置PowerMock以解决Cobertura冲突?
A1: 在Maven项目的pom.xml文件中,可以添加以下配置来解决Cobertura与PowerMock的冲突:
- <build>
- <plugins>
- <plugin>
- <artifactId>mavensurefireplugin</artifactId>
- <configuration>
- <forkMode>pertest</forkMode>
- </configuration>
- </plugin>
- </plugins>
- </build>
Q2: 为什么在使用PowerMock时会遇到java.lang.SecurityException
?
A2: 这个错误通常是由于JAR文件签名问题引起的,当多个类由不同的签名者签名时,可能会引发安全异常,确保所有使用的JAR文件都由相同的证书签名,或者在测试环境中忽略签名验证。