【问题标题】:Java Mockito JUnit Test / Mock Class with a constructor that contains a abstract Method call带有包含抽象方法调用的构造函数的 Java Mockito JUnit 测试/模拟类
【发布时间】:2015-01-27 13:19:16
【问题描述】:

我有一个关于单元测试和模拟测试的问题。 我想测试一个与其他模块有依赖关系的模块。 问题是,我在测试运行时收到了这条消息:

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/faces/component/UIComponent
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
    at java.lang.Class.privateGetPublicMethods(Unknown Source)
    at java.lang.Class.getMethods(Unknown Source)
    at org.mockito.internal.runners.util.TestMethodsFinder.hasTestMethods(TestMethodsFinder.java:13)
    at org.mockito.internal.runners.RunnerFactory.create(RunnerFactory.java:33)
    at org.mockito.runners.MockitoJUnitRunner.<init>(MockitoJUnitRunner.java:57)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21)
    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:26)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

例如:

 public void MyMethod(){     
   PickList myPickList = new PickList();
   ... some code ...
   myPickList.getSource(); 
   myPickList.getTarget();
 }

PickList 构造函数包含:

PickList(){setRendererType(rendererValue);}

setRendererType 方法是扩展 UIComponent 的抽象方法。

我的问题,我如何测试/模拟(仅允许 Java 1.7、JUnit4 和 Mockito 1.10.19)这种方法?

是否可以模拟/避免构造函数调用?

我可以模拟更深层次的依赖关系吗?

【问题讨论】:

    标签: java unit-testing junit mocking mockito


    【解决方案1】:

    那么几件事。

    首先,您可以使用 JMockit 或 Powermock 模拟构造函数调用。

    其次,你不应该从构造函数中调用抽象方法。对于任何非最终方法也是如此。您永远不应该从构造函数中调用任何非最终实例方法。这是因为您在子类的构造函数完全执行之前调用子类的实例方法。因此,子类中可能存在由构造函数填充的实例字段。在对实例方法的调用(通过超级构造函数调用)中,这些字段尚未填充,从而打破了实例方法的期望。

    更新:但是,看看您的问题,setRendererTypePickList 并不抽象。它是UIComponent 中的一个抽象方法,但PickList 或某些父类必须实现它,因此PickList 它不是抽象的。但是,关于非最终方法的规则仍然适用。

    【讨论】:

    • 感谢您的快速回答,这是正确的,PickList 类暗示了 UIComponent,但setRendererType 引用了 UIComponentBase,这是抽象的。我想从 PickList 中模拟的所有内容都是when( picklist.getValue() ).thenReturn( something );,所以我得到了我的东西对象。失败跟踪来自此测试代码行PickList picklist = mock( PickList.class );。我只能使用:Mockito 1.10.19、Java 1.7 和 JUnit4。我希望你能帮忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 2011-11-17
    • 2023-03-04
    相关资源
    最近更新 更多