All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.junit.contrib.java.lang.system.ExpectedSystemExit Maven / Gradle / Ivy

There is a newer version: 1.19.0
Show newest version
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();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy