Powermock - java.lang.IllegalStateException: Failed to transform class

2022-09-01 05:14:37

描述:

我正在尝试从类中测试静态方法。我正在使用powerMock(1.6.2)+ mockito(1.10.19)与Junit4(4.12)和java8一起进行模拟。

问题:

获取错误:“无法转换名称为 com.gs.ops.domain.StaticClass 的类 原因: java.io.IOException: invalid 常量类型: 18”

尝试的解决方案:

  1. Googled threads for problem with powermock - mockito & java-8

  2. 从 powermock 中排除了 java assist,并添加了 java assist 3.19.0-GA

  3. 已尝试不同版本的 powermock(1.5.4、1.6.2...)

下面是异常堆栈跟踪:

 java.lang.IllegalStateException: Failed to transform class with name com.StaticClass. Reason: java.io.IOException: invalid constant type: 18
        at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:266)
        at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
        at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:340)
        at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:145)
        at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40)
        at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244)
        at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:61)
        at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)
        at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
        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:408)
        at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
        at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    Caused by: java.lang.RuntimeException: java.io.IOException: invalid constant type: 18
        at javassist.CtClassType.getClassFile2(CtClassType.java:203)
        at javassist.compiler.MemberResolver.lookupMethod(MemberResolver.java:110)
        at javassist.compiler.MemberResolver.lookupMethod(MemberResolver.java:96)
        at javassist.compiler.TypeChecker.atMethodCallCore(TypeChecker.java:704)
        at javassist.expr.NewExpr$ProceedForNew.setReturnType(NewExpr.java:243)
        at javassist.compiler.JvstTypeChecker.atCallExpr(JvstTypeChecker.java:146)
        at javassist.compiler.ast.CallExpr.accept(CallExpr.java:45)
        at javassist.compiler.TypeChecker.atVariableAssign(TypeChecker.java:248)
        at javassist.compiler.TypeChecker.atAssignExpr(TypeChecker.java:217)
        at javassist.compiler.ast.AssignExpr.accept(AssignExpr.java:38)
        at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:241)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:329)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:49)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:350)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:49)
        at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:404)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:354)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:49)
        at javassist.compiler.Javac.compileStmnt(Javac.java:568)
        at javassist.expr.NewExpr.replace(NewExpr.java:206)
        at org.powermock.core.transformers.impl.MainMockTransformer$PowerMockExpressionEditor.edit(MainMockTransformer.java:418)
        at javassist.expr.ExprEditor.loopBody(ExprEditor.java:211)
        at javassist.expr.ExprEditor.doit(ExprEditor.java:90)
        at javassist.CtClassType.instrument(CtClassType.java:1374)
        at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:74)
        at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:251)
        ... 24 more
    Caused by: java.io.IOException: invalid constant type: 18
        at javassist.bytecode.ConstPool.readOne(ConstPool.java:1090)
        at javassist.bytecode.ConstPool.read(ConstPool.java:1033)
        at javassist.bytecode.ConstPool.<init>(ConstPool.java:149)
        at javassist.bytecode.ClassFile.read(ClassFile.java:737)
        at javassist.bytecode.ClassFile.<init>(ClassFile.java:108)
        at javassist.CtClassType.getClassFile2(CtClassType.java:190)
        ... 49 more

庞邦文件:

<dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>1.6.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>1.6.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-reflect</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.19.0-GA</version>
        </dependency>

答案 1

Powermock 1.6.3 使用 javassist 3.15.2-GA,它不支持某些类型。使用3.18.2-GA javassist对我来说很有效。您可能希望覆盖项目中的依赖项。

    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.18.2-GA</version>
    </dependency>

您可能会面临另一个问题,其解决方案位于Mockito + PowerMock Linkage在模拟系统类时出错

希望这有帮助。


答案 2

因此,之前(字节码工具包)似乎存在问题,因为有一个已解决的JIRA票证-223javassist3.18.2

1 -要在pom.xml中找到javassist版本,可以使用taskmvn dependency

$ mvn dependency:tree | grep javassist
[INFO] |     \- org.javassist:javassist:jar:3.14.0-GA:compile

它由 ,powermock-module-junit4-rule

[INFO] +- org.powermock:powermock-module-junit4-rule:jar:1.4.9:test
[INFO] |  +- org.powermock:powermock-classloading-base:jar:1.4.9:test
[INFO] |  \- org.powermock:powermock-core:jar:1.4.9:compile
[INFO] |     \- org.javassist:javassist:jar:3.14.0-GA:compile

2 -因此,通过将版本显式更新为任何版本应该可以正常工作。javassist>= 3.18.2

因为,在我的情况下,我正在使用3.20.0-GA

    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.20.0-GA</version>
    </dependency>

工作例如。使用 scalatest

@PowerMockIgnore(Array("javax.management.*"))
@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[Configurator]))
class LogServiceSpec {

  @Test
  def initialises_log4j2_on_each_instance_call() {
    PowerMockito.mockStatic(classOf[Configurator])

    val logService1 = new LogService
    PowerMockito.verifyStatic(Mockito.times(1))
    Configurator.initialize(Matchers.anyString(), Matchers.eq("log4j.config"))
  }
}

推荐