001 package org.junit.rules;
002
003 import java.util.ArrayList;
004 import java.util.List;
005
006 import org.junit.runner.Description;
007 import org.junit.runners.model.MultipleFailureException;
008 import org.junit.runners.model.Statement;
009
010 /**
011 * A base class for Rules (like TemporaryFolder) that set up an external
012 * resource before a test (a file, socket, server, database connection, etc.),
013 * and guarantee to tear it down afterward:
014 *
015 * <pre>
016 * public static class UsesExternalResource {
017 * Server myServer= new Server();
018 *
019 * @Rule
020 * public ExternalResource resource= new ExternalResource() {
021 * @Override
022 * protected void before() throws Throwable {
023 * myServer.connect();
024 * };
025 *
026 * @Override
027 * protected void after() {
028 * myServer.disconnect();
029 * };
030 * };
031 *
032 * @Test
033 * public void testFoo() {
034 * new Client().run(myServer);
035 * }
036 * }
037 * </pre>
038 *
039 * @since 4.7
040 */
041 public abstract class ExternalResource implements TestRule {
042 public Statement apply(Statement base, Description description) {
043 return statement(base);
044 }
045
046 private Statement statement(final Statement base) {
047 return new Statement() {
048 @Override
049 public void evaluate() throws Throwable {
050 before();
051
052 List<Throwable> errors = new ArrayList<Throwable>();
053 try {
054 base.evaluate();
055 } catch (Throwable t) {
056 errors.add(t);
057 } finally {
058 try {
059 after();
060 } catch (Throwable t) {
061 errors.add(t);
062 }
063 }
064 MultipleFailureException.assertEmpty(errors);
065 }
066 };
067 }
068
069 /**
070 * Override to set up your specific external resource.
071 *
072 * @throws Throwable if setup fails (which will disable {@code after}
073 */
074 protected void before() throws Throwable {
075 // do nothing
076 }
077
078 /**
079 * Override to tear down your specific external resource.
080 */
081 protected void after() {
082 // do nothing
083 }
084 }