Using Eclipse 3.6.1
Java 1.6.0_26
JMockit 0.999.10
UPDATE: I was able to create a SSCCE, which I am posting below:
UPDATE2: Added DaemonHelper. Additionally, if I remove DaemonHelper from the constructor, I get a ClassCircularityError instead. Related?
I'm trying to do a partial mock of a class, while mocking several dependencies of the class, when I get an NPE from the Class loader. The NPE call stack is show below
I have a Daemon
Class like so:
public class Daemon extends DaemonParent {
public Daemon(ConfigParent config, DaemonHelper helper) {
super(config, helper);
}
@Override
public void execute() {
log("Starting");
if (config.test()) {
log("Testing");
}
log("Ending");
}
}
The Daemon has a Parent like so:
public abstract class DaemonParent extends Thread {
protected ConfigParent config;
protected DaemonHelper helper;
public DaemonParent(ConfigParent config, DaemonHelper helper) {
this.config = config;
this.helper = helper;
}
public abstract void execute();
public void log(String s) {
System.out.println(s);
}
}
There is a helper class like :
public class DaemonHelper extends Thread {
}
The Config looks like :
public class ConfigParent {
protected ConfigHelper helper;
public ConfigParent(ConfigHelper helper) {
this.helper = helper;
}
public boolean test() {
return false;
}
}
The Config Parent looks like :
public class ConfigParent implements Serializable {
protected ConfigHelper helper;
public ConfigParent(ConfigHelper helper) {
this.helper = helper;
}
public boolean test() {
return false;
}
}
And the Test looks like :
public class DaemonTest {
@Test
public void testExecute(final ConfigHelper ch, final DaemonHelper dh) {
final Config c = new Config(ch);
final Daemon d = new Daemon(c, dh);
new NonStrictExpectations(d) {
{
}
};
d.execute();
new Verifications() {{
d.log("Starting");
d.log("Ending");
}};
}
}
When I try to run this test, I get the following error. Note this error only pops up when the DaemonParent and Daemon Helper have java.lang.Thread as a superclass:
java.lang.NullPointerException
at java.lang.Thread.interrupted(Unknown Source)
at sun.misc.Resource.getBytes(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(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 org.junit.internal.runners.model.EachTestNotifier.addFailure(EachTestNotifier.java:23)
at org.junit.runners.ParentRunner.run(ParentRunner.java:242)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
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)
I tried commenting out the NonStrictExpectations
block and the Verifications
block, and I get the same error.
The NPE is thrown from a call to currentThread()... which I have no Idea how it could fail.
Any ideas?
It turns out the problem that that the root superclass of Daemon is java.lang.Thread
, which caused JMockit to have trouble. The solution was static partial mocking of the methods required by the test.
public class DaemonTest {
@Test
public void testExecute(final ConfigHelper ch, final DaemonHelper dh) {
new NonStrictExpectations(d) {
@Mocked({"log"}
Daemon d;
@Mocked({"()"})
DaemonHelper dh;
{
}
};
final Config c = new Config(ch);
final Daemon d = new Daemon(c, dh);
d.execute();
new Verifications() {{
d.log("Starting");
d.log("Ending");
}};
}
}