PowerMock& JavaAssist"无法转换类"

时间:2016-03-31 06:31:14

标签: java javafx junit powermock

在使用PowerMock进行单元测试时,我遇到了一些特定类及其转换的问题。

我已经查看了许多SO响应,并尝试了许多PowerMock,JUnit,JavaAssist(重写依赖项)的组合,但无法找到适用于此类的组合。

(PowerMock,Junit和Javaassist的某些组合没有这个问题,但是无效的堆栈帧一个.....所以也在那里停留 - 但我必须在单独的SO问题中解决这个问题)。

如果我在@PrepareForTest()列表中包含ToplevelPanel类,那么它将失败。其他JavaFX类(如Pane.class)没有问题。

ToplevelPanel没有什么特别奇怪的事情:

public class ToplevelPane extends Region implements BlockContainer, Bundleable {

Bundleable没有@Serializable注释或任何特殊内容。

当我测试ToplevelPanel并希望它在@PrepareForTest中能够通过whenNew()以及当我测试其他类并想要模拟它时捕获new()时,这会失败。

如果有人可以共享一个pom.xml或版本组合,允许我使用@PrepareForTest这样的类,包括捕获whenNew(),那将非常感激。

在这篇文章的底部,您可以找到失败的堆栈跟踪。

的pom.xml

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <junit.version>4.11</junit.version>
    <powermock.version>1.5.1</powermock.version>
  </properties>

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>${junit.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>${powermock.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>${powermock.version}</version>
  <scope>test</scope>
</dependency>

单元测试代码

import nl.utwente.viskell.haskell.env.Environment;
import nl.utwente.viskell.haskell.type.Type;
import nl.utwente.viskell.ui.ToplevelPane;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Type.class, ToplevelPane.class, Environment.class})
public class ValueBlockTest {
    private ToplevelPane mockToplevelPane;

    @Before
    public void Setup() {
        mockToplevelPane = mock(ToplevelPane.class, RETURNS_DEEP_STUBS);
        Environment mockEnv = mock(Environment.class);
        Type mockType = mock(Type.class);
        when(mockEnv.buildType(any())).thenReturn(mockType);
        when(mockToplevelPane.getEnvInstance()).thenReturn(mockEnv);
    }

    @Test
    public void outputTest() throws Exception {
        ConstantBlock block = new ConstantBlock(mockToplevelPane, Type.con("Float"), "0.0", true);
        block.setValue("6");
        assertEquals(block.getValue(), "6");
    }
}

失败Stacktrace

  

java.lang.IllegalStateException:无法转换具有名称的类   nl.utwente.viskell.ui.ToplevelPane。原因:   javassist.bytecode.InterfaceMethodrefInfo无法强制转换为   javassist.bytecode.MethodrefInfo at   org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:219)     在   org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:147)     在   org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67)     在java.lang.ClassLoader.loadClass(ClassLoader.java:357)at   java.lang.Class.forName0(Native Method)at   java.lang.Class.forName(Class.java:348)at   sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)     在   sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)     在   sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)     在   sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:439)     在   sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:420)     在   sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)     在   sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)     在   sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)     在   sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)     在   sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)     在   sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)     在java.lang.Class.createAnnotationData(Class.java:3521)at   java.lang.Class.annotationData(Class.java:3510)at   java.lang.Class.getAnnotation(Class.java:3415)at   org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:52)     在   org.junit.internal.runners.TestClass.getAnnotatedMethods(TestClass.java:45)     在   org.junit.internal.runners.MethodValidator.validateTestMethods(MethodValidator.java:71)     在   org.junit.internal.runners.MethodValidator.validateStaticMethods(MethodValidator.java:44)     在   org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:50)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl。(PowerMockJUnit44RunnerDelegateImpl.java:70)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl。(PowerMockJUnit47RunnerDelegateImpl.java:42)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl。(PowerMockJUnit49RunnerDelegateImpl.java:25)     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native   方法)at   sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)     在   sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:422)     在   org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:143)     在   org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:39)     在   org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:217)     在   org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl。(JUnit4TestSuiteChunkerImpl.java:59)     在   org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner。(AbstractCommonPowerMockRunner.java:32)     在   org.powermock.modules.junit4.PowerMockRunner。(PowerMockRunner.java:33)     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native   方法)at   sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)     在   sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:422)     在   org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29)     在   org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21)     在   org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)     在   org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)     在   org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)     在   org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)     在   com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:41)     在   com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)     在   com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)   引起:java.lang.ClassCastException:   javassist.bytecode.InterfaceMethodrefInfo无法强制转换为   javassist.bytecode.MethodrefInfo at   javassist.bytecode.ConstPool.getMethodrefType(ConstPool.java:452)at at   javassist.bytecode.stackmap.Tracer.doInvokeMethod(Tracer.java:800)at at   javassist.bytecode.stackmap.Tracer.doOpcode148_201(Tracer.java:597)     在javassist.bytecode.stackmap.Tracer.doOpcode(Tracer.java:81)at   javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:187)at at   javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:199)at at   javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:164)at at   javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:108)at at   javassist.bytecode.MethodInfo.rebuildStackMap(MethodInfo.java:423)at at   javassist.bytecode.MethodInfo.rebuildStackMapIf6(MethodInfo.java:405)     在javassist.CtBehavior.insertBefore(CtBehavior.java:768)at   javassist.CtBehavior.insertBefore(CtBehavior.java:734)at   org.powermock.core.transformers.impl.MainMockTransformer.modifyMethod(MainMockTransformer.java:206)     在   org.powermock.core.transformers.impl.MainMockTransformer.allowMockingOfStaticAndFinalAndNativeMethods(MainMockTransformer.java:142)     在   org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:65)     在   org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:215)     ......还有56个

1 个答案:

答案 0 :(得分:0)

不幸的是,如果您确实需要准备测试ToplevelPane类,则此问题现在无法解决。但我不确定是否需要它。 我注意到ToplevelPane类没有静态或最终方法。如果从注释中删除ToplevelPane,则测试会因另一个错误而失败。

  

java.lang.ExceptionInInitializerError at   sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)     在   sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)     在   sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)     在java.lang.Class.newInstance(Class.java:442)at   sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)at   javafx.fxml.FXMLLoader $ InstanceDeclarationElement.constructValue(FXMLLoader.java:1009)     在   javafx.fxml.FXMLLoader $ ValueElement.processStartElement(FXMLLoader.java:746)     在javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)     在javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)at   javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)at at   javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)at at   nl.utwente.viskell.ui.ComponentLoader.loadFXML(ComponentLoader.java:25)     在   nl.utwente.viskell.ui.components.ValueBlock。(ValueBlock.java:48)     在   nl.utwente.viskell.ui.components.ConstantBlock。(ConstantBlock.java:25)     在ValueBlockTest.outputTest(ValueBlockTest.java:33)at   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:498)at   org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)at   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:316)     在   org.junit.internal.runners.MethodRoadie $ 2.run(MethodRoadie.java:89)     在   org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:300)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.access 100 $(PowerMockJUnit47RunnerDelegateImpl.java:59)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner $ TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:288)     在   org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)     在org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:208)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:147)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ 1.run(PowerMockJUnit44RunnerDelegateImpl.java:121)     在   org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)     在   org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)     在   org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:123)     在   org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:123)     在   org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)     在   org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)     在org.junit.runner.JUnitCore.run(JUnitCore.java:137)at   com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)     在   com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)     在   com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:498)at   com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)   引起:java.lang.IllegalStateException:Toolkit未初始化     在   com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)     在   com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)     在   com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)     在   com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)     在javafx.scene.control.Control。(Control.java:87)... 51   更

如果将Javassist更新为最新版本,则CgLib会创建用Javassist代码修改的奇怪代理类,因此JVM会抛出java.lang.VerifyError。 Mockito 1和PowerMock使用的cglib 2不再受支持。

自第2版以来,Mockito已迁移到ByteButty,但它只是测试版。 PowerMock也将转向ByteButty,但我怀疑它会早于6月底。

我将尝试在下一个PowerMock版本(1.6.5)中解决此问题,但我不确定它是否可行。

我在错误跟踪器中创建了issue。顺便说一句,如果javafx.scene.layout.Region被嘲笑,我可以重现这个问题。