org.junit.contrib.java.lang.system.ExpectedSystemExit Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of system-rules Show documentation
Show all versions of system-rules Show documentation
A collection of JUnit rules for testing code which uses java.lang.System.
package org.junit.contrib.java.lang.system;
import static java.lang.System.getSecurityManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.contrib.java.lang.system.internal.CheckExitCalled;
import org.junit.contrib.java.lang.system.internal.NoExitSecurityManager;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* The {@code ExpectedSystemExit} allows in-test specification of expected
* {@code System.exit(...)} calls.
*
*
* If your code calls {@code System.exit(),} then your test stops and doesn't
* finish. The {@code ExpectedSystemExit} rule allows in-test specification of
* expected {@code System.exit()} calls. Furthermore you cannot use JUnit's
* assert methods because of the abnormal termination of your code. As a
* substitute you can provide an {@code Assertion} object to the
* {@code ExpectedSystemExit} rule.
*
*
* Some care must be taken if your system under test creates a new thread and
* this thread calls {@code System.exit()}. In this case you have to ensure that
* the test does not finish before {@code System.exit()} is called.
*
*
* public class AppWithExit {
* public static String message;
*
* public static int doSomethingAndExit() {
* message = "exit ...";
* System.exit(1);
* }
*
* public static int doNothing() {
* }
* }
*
*
*
* public void AppWithExitTest {
* @Rule
* public final ExpectedSystemExit exit = ExpectedSystemExit.none();
*
* @Test
* public void exits() {
* exit.expectSystemExit();
* AppWithExit.doSomethingAndExit();
* }
*
* @Test
* public void exitsWithStatusCode1() {
* exit.expectSystemExitWithStatus(1);
* AppWithExit.doSomethingAndExit();
* }
*
* @Test
* public void writesMessage() {
* exit.checkAssertionAfterwards(new Assertion() {
* public void checkAssertion() {
* assertEquals("exit ...", AppWithExit.message);
* }
* });
* AppWithExit.doSomethingAndExit();
* }
*
* @Test
* public void systemExitWithStatusCode1() {
* exit.expectSystemExitWithStatus(1);
* AppWithExit.doSomethingAndExit();
* }
*
* @Test
* public void noSystemExit() {
* AppWithExit.doNothing();
* //passes
* }
* }
*
*/
public class ExpectedSystemExit implements TestRule {
public static ExpectedSystemExit none() {
return new ExpectedSystemExit();
}
private final Collection assertions = new ArrayList();
private boolean expectExit = false;
private Integer expectedStatus = null;
private ExpectedSystemExit() {
}
public void expectSystemExitWithStatus(int status) {
expectSystemExit();
expectedStatus = status;
}
public void expectSystemExit() {
expectExit = true;
}
public void checkAssertionAfterwards(Assertion assertion) {
assertions.add(assertion);
}
public Statement apply(final Statement base, Description description) {
ProvideSecurityManager noExitSecurityManagerRule = createNoExitSecurityManagerRule();
Statement statement = createStatement(base);
return noExitSecurityManagerRule.apply(statement, description);
}
private ProvideSecurityManager createNoExitSecurityManagerRule() {
NoExitSecurityManager noExitSecurityManager = new NoExitSecurityManager(
getSecurityManager());
return new ProvideSecurityManager(noExitSecurityManager);
}
private Statement createStatement(final Statement base) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (CheckExitCalled ignored) {
}
checkSystemExit();
checkAssertions();
}
};
}
private void checkSystemExit() {
NoExitSecurityManager securityManager = (NoExitSecurityManager) getSecurityManager();
if (securityManager.isCheckExitCalled())
handleSystemExitWithStatus(securityManager.getStatusOfFirstCheckExitCall());
else
handleMissingSystemExit();
}
private void handleMissingSystemExit() {
if (expectExit)
fail("System.exit has not been called.");
}
private void handleSystemExitWithStatus(int status) {
if (!expectExit)
fail("Unexpected call of System.exit(" + status + ").");
else if (expectedStatus != null)
assertEquals("Wrong exit status", expectedStatus, Integer.valueOf(status));
}
private void checkAssertions() throws Exception {
for (Assertion assertion : assertions)
assertion.checkAssertion();
}
}