Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with System.exit(0) in JUnit tests

Tags:

java

junit

I am implementing some tests for an existing Java Swing application, so that I can safely refactor and extend the code without breaking anything. I started with some unit tests in JUnit, since that seems the simplest way to get started, but now my priority is to create some end-to-end tests to exercise the application as a whole.

I am starting the application afresh in each test by putting each test method in a separate test case, and using the fork="yes" option in Ant's junit task. However, some of the use cases I would like to implement as tests involve the user exiting the application, which results in one of the methods calling System.exit(0). This is regarded by JUnit as an error: junit.framework.AssertionFailedError: Forked Java VM exited abnormally.

Is there a way to tell JUnit that exiting with a return code of zero is actually OK?

like image 418
Ben Avatar asked May 26 '11 15:05

Ben


People also ask

How do you use System Exit 0?

exit(0) method terminates JVM which results in termination of the currently running program too. Status is the single parameter that the method takes. If the status is 0, it indicates the termination is successful. Let's see practical implementations of System.

Can we mock system exit?

You actually can mock or stub out the System. exit method, in a JUnit test. Vote down reason: The problem with this solution is that if System. exit is not the last line in the code (i.e. inside if condition), the code will continue to run.

Why do we use system Exit 0?

exit(0) : Indicates successful termination. exit(1) or exit(-1) or any non-zero value – indicates unsuccessful termination.

What can I use instead of system exit in Java?

The main alternative is Runtime. getRuntime(). halt(0) , described as "Forcibly terminates the currently running Java virtual machine". This does not call shutdown hooks or exit finalizers, it just exits.


2 Answers

The library System Rules has a JUnit rule called ExpectedSystemExit. With this rule you are able to test code, that calls System.exit(...):

public class MyTest {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void systemExitWithArbitraryStatusCode() {
        exit.expectSystemExit();
        /* the code under test, which calls System.exit(...)
         * with an arbitrary status
         */
    }

    @Test
    public void systemExitWithSelectedStatusCode0() {
        exit.expectSystemExitWithStatus(0);
        //the code under test, which calls System.exit(0)
    }
}

System Rules needs at least JUnit 4.9.

Full disclosure: I'm the author of System Rules.

like image 173
Stefan Birkner Avatar answered Sep 19 '22 12:09

Stefan Birkner


If anybody needs this functionality for JUnit 5, I've written an extension to do this. This is a simple annotation you can use to tell your test case to expect and exit status code or a specific exit status code.

For example, any exit code will do:

public class MyTestCases { 

    @Test
    @ExpectSystemExit
    public void thatSystemExitIsCalled() {
        System.exit(1);
    }
}

If we want to look for a specific code:

public class MyTestCases {

    @Test
    @ExpectSystemExitWithStatus(1)
    public void thatSystemExitIsCalled() {
        System.exit(1);
    }
}
like image 40
Todd Avatar answered Sep 17 '22 12:09

Todd