1 /* 2 * Copyright (c) 2018 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal.runners; 6 7 import org.junit.runner.Description; 8 import org.junit.runner.manipulation.Filter; 9 import org.junit.runner.manipulation.NoTestsRemainException; 10 import org.junit.runner.notification.Failure; 11 import org.junit.runner.notification.RunListener; 12 import org.junit.runner.notification.RunNotifier; 13 import org.junit.runners.BlockJUnit4ClassRunner; 14 import org.junit.runners.model.FrameworkMethod; 15 import org.junit.runners.model.InitializationError; 16 import org.junit.runners.model.Statement; 17 import org.mockito.Mockito; 18 import org.mockito.MockitoAnnotations; 19 import org.mockito.internal.junit.DefaultTestFinishedEvent; 20 import org.mockito.internal.junit.MockitoTestListener; 21 import org.mockito.internal.util.Supplier; 22 23 public class DefaultInternalRunner implements InternalRunner { 24 25 private final BlockJUnit4ClassRunner runner; 26 DefaultInternalRunner(Class<?> testClass, final Supplier<MockitoTestListener> listenerSupplier)27 public DefaultInternalRunner(Class<?> testClass, final Supplier<MockitoTestListener> listenerSupplier) throws InitializationError { 28 runner = new BlockJUnit4ClassRunner(testClass) { 29 30 public Object target; 31 private MockitoTestListener mockitoTestListener; 32 33 protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) { 34 this.target = target; 35 // get new test listener and add it to the framework 36 mockitoTestListener = listenerSupplier.get(); 37 Mockito.framework().addListener(mockitoTestListener); 38 // init annotated mocks before tests 39 MockitoAnnotations.initMocks(target); 40 return super.withBefores(method, target, statement); 41 } 42 43 public void run(final RunNotifier notifier) { 44 RunListener listener = new RunListener() { 45 private boolean started; 46 Throwable failure; 47 48 @Override 49 public void testStarted(Description description) throws Exception { 50 started = true; 51 } 52 53 @Override 54 public void testFailure(Failure failure) throws Exception { 55 this.failure = failure.getException(); 56 // If the test fails during the setup, `testFinished` is never invoked 57 // Therefore, if we have not started, cleanup the testlistener 58 if (!started && mockitoTestListener != null) { 59 Mockito.framework().removeListener(mockitoTestListener); 60 } 61 } 62 63 @Override 64 public void testFinished(Description description) throws Exception { 65 try { 66 if (mockitoTestListener != null) { 67 Mockito.framework().removeListener(mockitoTestListener); 68 mockitoTestListener.testFinished(new DefaultTestFinishedEvent(target, description.getMethodName(), failure)); 69 } 70 Mockito.validateMockitoUsage(); 71 } catch (Throwable t) { 72 //In order to produce clean exception to the user we need to fire test failure with the right description 73 //Otherwise JUnit framework will report failure with some generic test name 74 notifier.fireTestFailure(new Failure(description, t)); 75 } 76 } 77 }; 78 notifier.addListener(listener); 79 super.run(notifier); 80 } 81 }; 82 } 83 run(final RunNotifier notifier)84 public void run(final RunNotifier notifier) { 85 runner.run(notifier); 86 } 87 getDescription()88 public Description getDescription() { 89 return runner.getDescription(); 90 } 91 filter(Filter filter)92 public void filter(Filter filter) throws NoTestsRemainException { 93 runner.filter(filter); 94 } 95 } 96