1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.runners;
6
7import java.lang.reflect.InvocationTargetException;
8
9import org.junit.runner.Description;
10import org.junit.runner.Runner;
11import org.junit.runner.manipulation.Filter;
12import org.junit.runner.manipulation.Filterable;
13import org.junit.runner.manipulation.NoTestsRemainException;
14import org.junit.runner.notification.Failure;
15import org.junit.runner.notification.RunListener;
16import org.junit.runner.notification.RunNotifier;
17import org.mockito.internal.debugging.WarningsCollector;
18import org.mockito.internal.runners.RunnerFactory;
19import org.mockito.internal.runners.RunnerImpl;
20import org.mockito.internal.util.junit.JUnitFailureHacker;
21
22/**
23 * Experimental implementation that suppose to improve tdd/testing experience.
24 * Don't hesitate to send feedback to mockito@googlegroups.com
25 * <b>It is very likely it will change in the next version!</b>
26 * <p>
27 * This runner does exactly what {@link MockitoJUnitRunner} does but also
28 * adds extra Mocktio hints to the exception message.
29 * The point is that Mockito should help the tdd developer to quickly figure out if the test fails for the right reason and track the reason.
30 * <p>
31 * The implemntation is pretty hacky - it uses brute force of reflection to modify the exception message and add extra mockito hints.
32 * You've been warned.
33 * <p>
34 * Do you think it is useful or not? Drop us an email at mockito@googlegroups.com
35 * <p>
36 * Experimental implementation - will change in future!
37 */
38public class VerboseMockitoJUnitRunner extends Runner implements Filterable {
39
40    private RunnerImpl runner;
41
42    public VerboseMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
43        this(new RunnerFactory().create(klass));
44    }
45
46    VerboseMockitoJUnitRunner(RunnerImpl runnerImpl) {
47        this.runner = runnerImpl;
48    }
49
50    @Override
51    public void run(RunNotifier notifier) {
52
53        //a listener that changes the failure's exception in a very hacky way...
54        RunListener listener = new RunListener() {
55
56            WarningsCollector warningsCollector;
57
58            @Override
59            public void testStarted(Description description) throws Exception {
60                warningsCollector = new WarningsCollector();
61            }
62
63            @Override
64            public void testFailure(final Failure failure) throws Exception {
65                String warnings = warningsCollector.getWarnings();
66                new JUnitFailureHacker().appendWarnings(failure, warnings);
67            }
68        };
69
70        notifier.addFirstListener(listener);
71
72        runner.run(notifier);
73    }
74
75    @Override
76    public Description getDescription() {
77        return runner.getDescription();
78    }
79
80    public void filter(Filter filter) throws NoTestsRemainException {
81        //filter is required because without it UnrootedTests show up in Eclipse
82        runner.filter(filter);
83    }
84}