1/*
2 * Copyright (c) 2016 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.internal.runners;
6
7import org.junit.runner.Description;
8import org.junit.runner.manipulation.Filter;
9import org.junit.runner.manipulation.NoTestsRemainException;
10import org.junit.runner.notification.RunNotifier;
11import org.mockito.Mockito;
12import org.mockito.internal.junit.UnnecessaryStubbingsReporter;
13import org.mockito.internal.runners.util.FailureDetector;
14
15public class StrictRunner implements InternalRunner {
16
17    private final Class<?> testClass;
18    private final InternalRunner runner;
19    private boolean filterRequested;
20
21    /**
22     * @param runner - the runner to wrap around
23     * @param testClass - for reporting purposes
24     */
25    public StrictRunner(InternalRunner runner, Class<?> testClass) {
26        this.runner = runner;
27        this.testClass = testClass;
28    }
29
30    public void run(RunNotifier notifier) {
31        //TODO need to be able to opt in for full stack trace instead of just relying on the stack trace filter
32        UnnecessaryStubbingsReporter reporter = new UnnecessaryStubbingsReporter();
33        FailureDetector listener = new FailureDetector();
34
35        Mockito.framework().addListener(reporter);
36        try {
37            // add listener that detects test failures
38            notifier.addListener(listener);
39            runner.run(notifier);
40        } finally {
41            Mockito.framework().removeListener(reporter);
42        }
43
44        if (!filterRequested && listener.isSuccessful()) {
45            //only report when:
46            //1. if all tests from given test have ran (filter requested is false)
47            //   Otherwise we would report unnecessary stubs even if the user runs just single test from the class
48            //2. tests are successful (we don't want to add an extra failure on top of any existing failure, to avoid confusion)
49            reporter.validateUnusedStubs(testClass, notifier);
50        }
51    }
52
53    public Description getDescription() {
54        return runner.getDescription();
55    }
56
57    public void filter(Filter filter) throws NoTestsRemainException {
58        filterRequested = true;
59        runner.filter(filter);
60    }
61}
62