    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     *  &#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     */
    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    }