001package org.junit.rules;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import org.junit.runner.Description;
007import org.junit.runners.model.MultipleFailureException;
008import 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 *  &#064;Rule
020 *  public ExternalResource resource= new ExternalResource() {
021 *      &#064;Override
022 *      protected void before() throws Throwable {
023 *          myServer.connect();
024 *         };
025 *
026 *      &#064;Override
027 *      protected void after() {
028 *          myServer.disconnect();
029 *         };
030 *     };
031 *
032 *  &#064;Test
033 *  public void testFoo() {
034 *      new Client().run(myServer);
035 *     }
036 * }
037 * </pre>
038 *
039 * @since 4.7
040 */
041public 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}