001    package org.junit.runners;
002    
003    import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR;
004    import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
005    
006    import java.util.List;
007    import java.util.concurrent.ConcurrentHashMap;
008    
009    import org.junit.After;
010    import org.junit.Before;
011    import org.junit.Ignore;
012    import org.junit.Rule;
013    import org.junit.Test;
014    import org.junit.Test.None;
015    import org.junit.internal.runners.model.ReflectiveCallable;
016    import org.junit.internal.runners.statements.ExpectException;
017    import org.junit.internal.runners.statements.Fail;
018    import org.junit.internal.runners.statements.FailOnTimeout;
019    import org.junit.internal.runners.statements.InvokeMethod;
020    import org.junit.internal.runners.statements.RunAfters;
021    import org.junit.internal.runners.statements.RunBefores;
022    import org.junit.rules.RunRules;
023    import org.junit.rules.TestRule;
024    import org.junit.runner.Description;
025    import org.junit.runner.notification.RunNotifier;
026    import org.junit.runners.model.FrameworkMethod;
027    import org.junit.runners.model.InitializationError;
028    import org.junit.runners.model.MultipleFailureException;
029    import org.junit.runners.model.Statement;
030    
031    /**
032     * Implements the JUnit 4 standard test case class model, as defined by the
033     * annotations in the org.junit package. Many users will never notice this
034     * class: it is now the default test class runner, but it should have exactly
035     * the same behavior as the old test class runner ({@code JUnit4ClassRunner}).
036     * <p>
037     * BlockJUnit4ClassRunner has advantages for writers of custom JUnit runners
038     * that are slight changes to the default behavior, however:
039     *
040     * <ul>
041     * <li>It has a much simpler implementation based on {@link Statement}s,
042     * allowing new operations to be inserted into the appropriate point in the
043     * execution flow.
044     *
045     * <li>It is published, and extension and reuse are encouraged, whereas {@code
046     * JUnit4ClassRunner} was in an internal package, and is now deprecated.
047     * </ul>
048     * <p>
049     * In turn, in 2009 we introduced {@link Rule}s.  In many cases where extending
050     * BlockJUnit4ClassRunner was necessary to add new behavior, {@link Rule}s can
051     * be used, which makes the extension more reusable and composable.
052     *
053     * @since 4.5
054     */
055    public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {
056        private final ConcurrentHashMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>();
057        /**
058         * Creates a BlockJUnit4ClassRunner to run {@code klass}
059         *
060         * @throws InitializationError if the test class is malformed.
061         */
062        public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
063            super(klass);
064        }
065    
066        //
067        // Implementation of ParentRunner
068        //
069    
070        @Override
071        protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
072            Description description = describeChild(method);
073            if (isIgnored(method)) {
074                notifier.fireTestIgnored(description);
075            } else {
076                runLeaf(methodBlock(method), description, notifier);
077            }
078        }
079        
080        /**
081         * Evaluates whether {@link FrameworkMethod}s are ignored based on the
082         * {@link Ignore} annotation.
083         */
084        @Override
085        protected boolean isIgnored(FrameworkMethod child) {
086            return child.getAnnotation(Ignore.class) != null;
087        }
088    
089        @Override
090        protected Description describeChild(FrameworkMethod method) {
091            Description description = methodDescriptions.get(method);
092    
093            if (description == null) {
094                description = Description.createTestDescription(getTestClass().getJavaClass(),
095                        testName(method), method.getAnnotations());
096                methodDescriptions.putIfAbsent(method, description);
097            }
098    
099            return description;
100        }
101    
102        @Override
103        protected List<FrameworkMethod> getChildren() {
104            return computeTestMethods();
105        }
106    
107        //
108        // Override in subclasses
109        //
110    
111        /**
112         * Returns the methods that run tests. Default implementation returns all
113         * methods annotated with {@code @Test} on this class and superclasses that
114         * are not overridden.
115         */
116        protected List<FrameworkMethod> computeTestMethods() {
117            return getTestClass().getAnnotatedMethods(Test.class);
118        }
119    
120        @Override
121        protected void collectInitializationErrors(List<Throwable> errors) {
122            super.collectInitializationErrors(errors);
123    
124            validateNoNonStaticInnerClass(errors);
125            validateConstructor(errors);
126            validateInstanceMethods(errors);
127            validateFields(errors);
128            validateMethods(errors);
129        }
130    
131        protected void validateNoNonStaticInnerClass(List<Throwable> errors) {
132            if (getTestClass().isANonStaticInnerClass()) {
133                String gripe = "The inner class " + getTestClass().getName()
134                        + " is not static.";
135                errors.add(new Exception(gripe));
136            }
137        }
138    
139        /**
140         * Adds to {@code errors} if the test class has more than one constructor,
141         * or if the constructor takes parameters. Override if a subclass requires
142         * different validation rules.
143         */
144        protected void validateConstructor(List<Throwable> errors) {
145            validateOnlyOneConstructor(errors);
146            validateZeroArgConstructor(errors);
147        }
148    
149        /**
150         * Adds to {@code errors} if the test class has more than one constructor
151         * (do not override)
152         */
153        protected void validateOnlyOneConstructor(List<Throwable> errors) {
154            if (!hasOneConstructor()) {
155                String gripe = "Test class should have exactly one public constructor";
156                errors.add(new Exception(gripe));
157            }
158        }
159    
160        /**
161         * Adds to {@code errors} if the test class's single constructor takes
162         * parameters (do not override)
163         */
164        protected void validateZeroArgConstructor(List<Throwable> errors) {
165            if (!getTestClass().isANonStaticInnerClass()
166                    && hasOneConstructor()
167                    && (getTestClass().getOnlyConstructor().getParameterTypes().length != 0)) {
168                String gripe = "Test class should have exactly one public zero-argument constructor";
169                errors.add(new Exception(gripe));
170            }
171        }
172    
173        private boolean hasOneConstructor() {
174            return getTestClass().getJavaClass().getConstructors().length == 1;
175        }
176    
177        /**
178         * Adds to {@code errors} for each method annotated with {@code @Test},
179         * {@code @Before}, or {@code @After} that is not a public, void instance
180         * method with no arguments.
181         */
182        @Deprecated
183        protected void validateInstanceMethods(List<Throwable> errors) {
184            validatePublicVoidNoArgMethods(After.class, false, errors);
185            validatePublicVoidNoArgMethods(Before.class, false, errors);
186            validateTestMethods(errors);
187    
188            if (computeTestMethods().size() == 0) {
189                errors.add(new Exception("No runnable methods"));
190            }
191        }
192    
193        protected void validateFields(List<Throwable> errors) {
194            RULE_VALIDATOR.validate(getTestClass(), errors);
195        }
196    
197        private void validateMethods(List<Throwable> errors) {
198            RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
199        }
200    
201        /**
202         * Adds to {@code errors} for each method annotated with {@code @Test}that
203         * is not a public, void instance method with no arguments.
204         */
205        protected void validateTestMethods(List<Throwable> errors) {
206            validatePublicVoidNoArgMethods(Test.class, false, errors);
207        }
208    
209        /**
210         * Returns a new fixture for running a test. Default implementation executes
211         * the test class's no-argument constructor (validation should have ensured
212         * one exists).
213         */
214        protected Object createTest() throws Exception {
215            return getTestClass().getOnlyConstructor().newInstance();
216        }
217    
218        /**
219         * Returns the name that describes {@code method} for {@link Description}s.
220         * Default implementation is the method's name
221         */
222        protected String testName(FrameworkMethod method) {
223            return method.getName();
224        }
225    
226        /**
227         * Returns a Statement that, when executed, either returns normally if
228         * {@code method} passes, or throws an exception if {@code method} fails.
229         *
230         * Here is an outline of the default implementation:
231         *
232         * <ul>
233         * <li>Invoke {@code method} on the result of {@code createTest()}, and
234         * throw any exceptions thrown by either operation.
235         * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
236         * expecting} attribute, return normally only if the previous step threw an
237         * exception of the correct type, and throw an exception otherwise.
238         * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
239         * timeout} attribute, throw an exception if the previous step takes more
240         * than the specified number of milliseconds.
241         * <li>ALWAYS run all non-overridden {@code @Before} methods on this class
242         * and superclasses before any of the previous steps; if any throws an
243         * Exception, stop execution and pass the exception on.
244         * <li>ALWAYS run all non-overridden {@code @After} methods on this class
245         * and superclasses after any of the previous steps; all After methods are
246         * always executed: exceptions thrown by previous steps are combined, if
247         * necessary, with exceptions from After methods into a
248         * {@link MultipleFailureException}.
249         * <li>ALWAYS allow {@code @Rule} fields to modify the execution of the
250         * above steps. A {@code Rule} may prevent all execution of the above steps,
251         * or add additional behavior before and after, or modify thrown exceptions.
252         * For more information, see {@link TestRule}
253         * </ul>
254         *
255         * This can be overridden in subclasses, either by overriding this method,
256         * or the implementations creating each sub-statement.
257         */
258        protected Statement methodBlock(FrameworkMethod method) {
259            Object test;
260            try {
261                test = new ReflectiveCallable() {
262                    @Override
263                    protected Object runReflectiveCall() throws Throwable {
264                        return createTest();
265                    }
266                }.run();
267            } catch (Throwable e) {
268                return new Fail(e);
269            }
270    
271            Statement statement = methodInvoker(method, test);
272            statement = possiblyExpectingExceptions(method, test, statement);
273            statement = withPotentialTimeout(method, test, statement);
274            statement = withBefores(method, test, statement);
275            statement = withAfters(method, test, statement);
276            statement = withRules(method, test, statement);
277            return statement;
278        }
279    
280        //
281        // Statement builders
282        //
283    
284        /**
285         * Returns a {@link Statement} that invokes {@code method} on {@code test}
286         */
287        protected Statement methodInvoker(FrameworkMethod method, Object test) {
288            return new InvokeMethod(method, test);
289        }
290    
291        /**
292         * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
293         * has the {@code expecting} attribute, return normally only if {@code next}
294         * throws an exception of the correct type, and throw an exception
295         * otherwise.
296         */
297        protected Statement possiblyExpectingExceptions(FrameworkMethod method,
298                Object test, Statement next) {
299            Test annotation = method.getAnnotation(Test.class);
300            return expectsException(annotation) ? new ExpectException(next,
301                    getExpectedException(annotation)) : next;
302        }
303    
304        /**
305         * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
306         * has the {@code timeout} attribute, throw an exception if {@code next}
307         * takes more than the specified number of milliseconds.
308         */
309        @Deprecated
310        protected Statement withPotentialTimeout(FrameworkMethod method,
311                Object test, Statement next) {
312            long timeout = getTimeout(method.getAnnotation(Test.class));
313            return timeout > 0 ? new FailOnTimeout(next, timeout) : next;
314        }
315    
316        /**
317         * Returns a {@link Statement}: run all non-overridden {@code @Before}
318         * methods on this class and superclasses before running {@code next}; if
319         * any throws an Exception, stop execution and pass the exception on.
320         */
321        protected Statement withBefores(FrameworkMethod method, Object target,
322                Statement statement) {
323            List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
324                    Before.class);
325            return befores.isEmpty() ? statement : new RunBefores(statement,
326                    befores, target);
327        }
328    
329        /**
330         * Returns a {@link Statement}: run all non-overridden {@code @After}
331         * methods on this class and superclasses before running {@code next}; all
332         * After methods are always executed: exceptions thrown by previous steps
333         * are combined, if necessary, with exceptions from After methods into a
334         * {@link MultipleFailureException}.
335         */
336        protected Statement withAfters(FrameworkMethod method, Object target,
337                Statement statement) {
338            List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
339                    After.class);
340            return afters.isEmpty() ? statement : new RunAfters(statement, afters,
341                    target);
342        }
343    
344        private Statement withRules(FrameworkMethod method, Object target,
345                Statement statement) {
346            List<TestRule> testRules = getTestRules(target);
347            Statement result = statement;
348            result = withMethodRules(method, testRules, target, result);
349            result = withTestRules(method, testRules, result);
350    
351            return result;
352        }
353    
354        private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules,
355                Object target, Statement result) {
356            for (org.junit.rules.MethodRule each : getMethodRules(target)) {
357                if (!testRules.contains(each)) {
358                    result = each.apply(result, method, target);
359                }
360            }
361            return result;
362        }
363    
364        private List<org.junit.rules.MethodRule> getMethodRules(Object target) {
365            return rules(target);
366        }
367    
368        /**
369         * @param target the test case instance
370         * @return a list of MethodRules that should be applied when executing this
371         *         test
372         */
373        protected List<org.junit.rules.MethodRule> rules(Object target) {
374            return getTestClass().getAnnotatedFieldValues(target, Rule.class,
375                    org.junit.rules.MethodRule.class);
376        }
377    
378        /**
379         * Returns a {@link Statement}: apply all non-static fields
380         * annotated with {@link Rule}.
381         *
382         * @param statement The base statement
383         * @return a RunRules statement if any class-level {@link Rule}s are
384         *         found, or the base statement
385         */
386        private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules,
387                Statement statement) {
388            return testRules.isEmpty() ? statement :
389                    new RunRules(statement, testRules, describeChild(method));
390        }
391    
392        /**
393         * @param target the test case instance
394         * @return a list of TestRules that should be applied when executing this
395         *         test
396         */
397        protected List<TestRule> getTestRules(Object target) {
398            List<TestRule> result = getTestClass().getAnnotatedMethodValues(target,
399                    Rule.class, TestRule.class);
400    
401            result.addAll(getTestClass().getAnnotatedFieldValues(target,
402                    Rule.class, TestRule.class));
403    
404            return result;
405        }
406    
407        private Class<? extends Throwable> getExpectedException(Test annotation) {
408            if (annotation == null || annotation.expected() == None.class) {
409                return null;
410            } else {
411                return annotation.expected();
412            }
413        }
414    
415        private boolean expectsException(Test annotation) {
416            return getExpectedException(annotation) != null;
417        }
418    
419        private long getTimeout(Test annotation) {
420            if (annotation == null) {
421                return 0;
422            }
423            return annotation.timeout();
424        }
425    }