How to test System.exit: Difference between revisions

From EggeWiki
No edit summary
 
mNo edit summary
 
Line 72: Line 72:
     }
     }
</pre>
</pre>
[[Category:Java]]

Latest revision as of 22:33, 30 September 2007

One might assume that testing a console app method which calls System.exit() would be impossible to do. By creating a SecurityManager we can detect and defer this call.

import java.io.IOException;
import java.security.Permission;
import java.util.Stack;

public class ConsoleAppUnitTest extends UnitTestCase {
    private SecurityManager existingSecurityManager;

    @Override
    protected void setUp() throws Exception {
        existingSecurityManager = System.getSecurityManager();
    }

    @Override
    protected void tearDown() throws Exception {
        System.setSecurityManager(existingSecurityManager);
    }

    private static class ExitCatchingSecurityManager extends SecurityManager {
        private Stack<Integer> exitCodes = new Stack<Integer>();

        public void checkExit(int status) {
            exitCodes.push(status);
            throw new SecurityException();
        }

        /**
         * This method is called before the original security manager can be replaced.  If this method does
         * not throw and exception then 'System.setSecurityManager(existingSecurityManager)' will work.
         * @param perm anything
         */
        @Override
        public void checkPermission(Permission perm) {
        }

        public int getLastExit() {
            return exitCodes.pop();
        }
    }

    public void testNoArgsExitsWithReturnCode() {
        ExitCatchingSecurityManager securityManager = new ExitCatchingSecurityManager();
        try {
            System.setSecurityManager(securityManager);
            ConsoleApp.main(new String[] { });
            fail();
        } catch (SecurityException e) {
            pass();
            assertEquals(2, securityManager.getLastExit());
            assertEquals(1, securityManager.getLastExit());
        }
    }
}

System.exit is called twice in this case, because the first System.exit throws an SecurityException which is caught in the 'catch Throwable' line. This trys to call System.exit again, and ends up throwing another exception.

    @SuppressWarnings({ "CallToSystemExit" })
    public static void main(String[] args) {
        try {
            if (args.length != 2) {
                System.err.println("Usage: inputFile outputFile");
                System.exit(1);
            }
            new ConsoleApp(args[0], args[1]).run();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
            System.exit(2);
        }
    }