1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/* 2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Copyright (c) 2007 Mockito contributors 3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This program is made available under the terms of the MIT License. 4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpackage org.mockito; 7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.configuration.AnnotationEngine; 9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.configuration.DefaultMockitoConfiguration; 10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.Reporter; 11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.base.MockitoException; 12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.configuration.GlobalConfiguration; 13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.reflection.FieldSetter; 14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.runners.MockitoJUnitRunner; 15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.annotation.Annotation; 17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.annotation.Retention; 18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.annotation.RetentionPolicy; 19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.annotation.Target; 20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.reflect.Field; 21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport static java.lang.annotation.ElementType.FIELD; 23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/** 25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * MockitoAnnotations.initMocks(this); initializes fields annotated with Mockito annotations. 26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <ul> 28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <li>Allows shorthand creation of objects required for testing.</li> 29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <li>Minimizes repetitive mock creation code.</li> 30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <li>Makes the test class more readable.</li> 31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <li>Makes the verification error easier to read because <b>field name</b> is used to identify the mock.</li> 32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * </ul> 33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <pre class="code"><code class="java"> 35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * public class ArticleManagerTest extends SampleBaseTestCase { 36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @Mock private ArticleCalculator calculator; 38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @Mock private ArticleDatabase database; 39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @Mock private UserProvider userProvider; 40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * private ArticleManager manager; 42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @Before public void setup() { 44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * manager = new ArticleManager(userProvider, database, calculator); 45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * } 46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * } 47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * public class SampleBaseTestCase { 49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * 50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @Before public void initMocks() { 51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * MockitoAnnotations.initMocks(this); 52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * } 53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * } 54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * </code></pre> 55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Read also about other annotations @{@link Spy}, @{@link Captor}, @{@link InjectMocks} 57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 58e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <b><code>MockitoAnnotations.initMocks(this)</code></b> method has to called to initialize annotated fields. 59e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 60e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * In above example, <code>initMocks()</code> is called in @Before (JUnit4) method of test's base class. 61e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class. 62e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * You can also put initMocks() in your JUnit runner (@RunWith) or use built-in runner: {@link MockitoJUnitRunner} 63e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 64e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class MockitoAnnotations { 65e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 66e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson /** 67e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Use top-level {@link org.mockito.Mock} annotation instead 68e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 69e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * When @Mock annotation was implemented as an inner class then users experienced problems with autocomplete features in IDEs. 70e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Hence @Mock was made a top-level class. 71e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 72e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * How to fix deprecation warnings? 73e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Typically, you can just <b>search:</b> import org.mockito.MockitoAnnotations.Mock; <b>and replace with:</b> import org.mockito.Mock; 74e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 75e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * If you're an existing user then sorry for making your code littered with deprecation warnings. 76e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This change was required to make Mockito better. 77e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 78e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson @Target( { FIELD }) 79e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson @Retention(RetentionPolicy.RUNTIME) 80e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson @Deprecated 81e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson public @interface Mock {} 82e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 83e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson /** 84e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Initializes objects annotated with Mockito annotations for given testClass: 85e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * @{@link org.mockito.Mock}, @{@link Spy}, @{@link Captor}, @{@link InjectMocks} 86e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 87e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * See examples in javadoc for {@link MockitoAnnotations} class. 88e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 89e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson public static void initMocks(Object testClass) { 90e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (testClass == null) { 91e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson throw new MockitoException("testClass cannot be null. For info how to use @Mock annotations see examples in javadoc for MockitoAnnotations class"); 92e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 93e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 94e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson AnnotationEngine annotationEngine = new GlobalConfiguration().getAnnotationEngine(); 95e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson Class<?> clazz = testClass.getClass(); 96e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 97e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson //below can be removed later, when we get read rid of deprecated stuff 98e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (annotationEngine.getClass() != new DefaultMockitoConfiguration().getAnnotationEngine().getClass()) { 99e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson //this means user has his own annotation engine and we have to respect that. 100e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson //we will do annotation processing the old way so that we are backwards compatible 101e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson while (clazz != Object.class) { 102e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson scanDeprecatedWay(annotationEngine, testClass, clazz); 103e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson clazz = clazz.getSuperclass(); 104e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 105e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 106e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 107e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson //anyway act 'the new' way 108e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson annotationEngine.process(testClass.getClass(), testClass); 109e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 110e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 111e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson static void scanDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Class<?> clazz) { 112e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson Field[] fields = clazz.getDeclaredFields(); 113e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 114e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson for (Field field : fields) { 115e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson processAnnotationDeprecatedWay(annotationEngine, testClass, field); 116e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 117e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 118e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 119e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson @SuppressWarnings("deprecation") 120e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson static void processAnnotationDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Field field) { 121e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson boolean alreadyAssigned = false; 122e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson for(Annotation annotation : field.getAnnotations()) { 123e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson Object mock = annotationEngine.createMockFor(annotation, field); 124e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (mock != null) { 125e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson throwIfAlreadyAssigned(field, alreadyAssigned); 126e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson alreadyAssigned = true; 127e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson try { 128e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson new FieldSetter(testClass, field).set(mock); 129e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } catch (Exception e) { 130e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson throw new MockitoException("Problems setting field " + field.getName() + " annotated with " 131e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson + annotation, e); 132e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 133e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 134e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 135e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 136e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 137e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson static void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) { 138e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (alreadyAssigned) { 139e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson new Reporter().moreThanOneAnnotationNotAllowed(field.getName()); 140e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 141e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 142e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson} 143