Patzde
Patzde

Reputation: 11

Java Mockito JUnit Test / Mock Class with a constructor that contains a abstract Method call

I've a question about unit and mocked tests. I want test a modul that has a dependency with a other modul. The problem is, I got this message by the Test Run:

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)

For Example:

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

The PickList constructor contains:

PickList(){setRendererType(rendererValue);}

The method setRendererType ist a abstract method extends UIComponent.

My questions, how can I test / mock (allowed only Java 1.7, JUnit4 and Mockito 1.10.19) this methods?

Is it possible to mock / avoid the constructor call?

Can I mock deeper dependencies?

Upvotes: 0

Views: 1180

Answers (1)

John B
John B

Reputation: 32949

So couple things.

First, you can mock constructor calls with JMockit or Powermock.

Second, you should NEVER call an abstract method from a constructor. This is also true for any non-final method. You should never call any non-final instance method from a constructor. This is because you are invoking an instance method on a sub-class prior to the sub-class' constructor being fully executed. So there might be instance fields in the sub-class that are populated by the constructor. In the call to the instance method (invoked via the super constructor) these fields are not yet populated breaking the expectation of the instance method.

Update: Looking at your question however, setRendererType is not abstract to PickList. It is an abstract method in UIComponent but PickList or some parent class must have implemented it so to PickList it is not abstract. However, the rule about non-final methods still applies.

Upvotes: 1

Related Questions