13 September 2008

NetBeans JUnit "Forked Java VM exited abnormally"

While trying to run a test case for a Java program in NetBeans using JUnit, my test suite failed and I found this error:

Forked Java VM exited abnormally. Please note the time in the report does not reflect the time until the VM exit.
junit.framework.AssertionFailedError
at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)

For some reason, NetBeans could not start a new virtual machine (I guess that's what the 'fork' means). I used NetBeans to debug the Ant test target and found in the nbproject\build-impl.xml file …

    <target name="-init-macrodef-junit">
        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <sequential>
                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
…

replacing fork="true" with fork="false" gave a more meaningful error message:

Exit from within execution engine, normal
org.netbeans.core.execution.ExitSecurityException: Exit from within execution engine, normal
…
        at org.netbeans.core.execution.SecMan.checkExit(SecMan.java:66)
        at org.netbeans.TopSecurityManager.checkExit(TopSecurityManager.java:145)
        at java.lang.Runtime.exit(Runtime.java:88)
        at java.lang.System.exit(System.java:906)
        at PrintLineNumber.Main.main(Main.java:16)
        at PrintLineNumber.MainTest.testMainNoArguments(MainTest.java:47)
        at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)

So, the NetBeans security manager does not allow my program to call System.exit(1), which is fair enough, otherwise (I guess) NetBeans would exit as well.

The location of the problem is in the test code below, created by NetBeans, which calls the main() method of my application:

44  public void testMain() {
45    System.out.println("main");
46    String[] args = null;
47    Main.main(args);
48  }

And here is the code that was tripping JUnit:

15      if (args == null || args.length != 2) {
16        System.exit(1);
17      }

My code was checking if the argument list is null, but that should never happen in normal use because the Java launcher always calls main() with a String array, not null. I removed the test for a null args and allowed a NullPointerException to be thrown. Then I added a test case for this situation:

  @Test(expected=NullPointerException.class)
  public void testMainNullArguments() {
    Main.main(null);
  }

Now, JUnit runs my test suite to completion!