Java Mockito JUnit Test / Mock类,包含一个包含抽象方法调用的构造函数

时间:2015-01-27 13:19:16

标签: java unit-testing junit mocking mockito

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

  

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 ist是一个抽象方法,扩展了UIComponent。

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

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

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

1 个答案:

答案 0 :(得分:1)

所以几件事。

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

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

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