/* * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockito; import org.mockito.configuration.AnnotationEngine; import org.mockito.configuration.DefaultMockitoConfiguration; import org.mockito.exceptions.Reporter; import org.mockito.exceptions.base.MockitoException; import org.mockito.internal.configuration.GlobalConfiguration; import org.mockito.internal.util.reflection.FieldSetter; import org.mockito.runners.MockitoJUnitRunner; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import static java.lang.annotation.ElementType.FIELD; /** * MockitoAnnotations.initMocks(this); initializes fields annotated with Mockito annotations. *
*
* public class ArticleManagerTest extends SampleBaseTestCase {
*
* @Mock private ArticleCalculator calculator;
* @Mock private ArticleDatabase database;
* @Mock private UserProvider userProvider;
*
* private ArticleManager manager;
*
* @Before public void setup() {
* manager = new ArticleManager(userProvider, database, calculator);
* }
* }
*
* public class SampleBaseTestCase {
*
* @Before public void initMocks() {
* MockitoAnnotations.initMocks(this);
* }
* }
*
* * Read also about other annotations @{@link Spy}, @{@link Captor}, @{@link InjectMocks} *
* MockitoAnnotations.initMocks(this)
method has to called to initialize annotated fields.
*
* In above example, initMocks()
is called in @Before (JUnit4) method of test's base class.
* For JUnit3 initMocks()
can go to setup()
method of a base class.
* You can also put initMocks() in your JUnit runner (@RunWith) or use built-in runner: {@link MockitoJUnitRunner}
*/
public class MockitoAnnotations {
/**
* Use top-level {@link org.mockito.Mock} annotation instead
*
* When @Mock annotation was implemented as an inner class then users experienced problems with autocomplete features in IDEs. * Hence @Mock was made a top-level class. *
* How to fix deprecation warnings? * Typically, you can just search: import org.mockito.MockitoAnnotations.Mock; and replace with: import org.mockito.Mock; *
* If you're an existing user then sorry for making your code littered with deprecation warnings. * This change was required to make Mockito better. */ @Target( { FIELD }) @Retention(RetentionPolicy.RUNTIME) @Deprecated public @interface Mock {} /** * Initializes objects annotated with Mockito annotations for given testClass: * @{@link org.mockito.Mock}, @{@link Spy}, @{@link Captor}, @{@link InjectMocks} *
* See examples in javadoc for {@link MockitoAnnotations} class. */ public static void initMocks(Object testClass) { if (testClass == null) { throw new MockitoException("testClass cannot be null. For info how to use @Mock annotations see examples in javadoc for MockitoAnnotations class"); } AnnotationEngine annotationEngine = new GlobalConfiguration().getAnnotationEngine(); Class> clazz = testClass.getClass(); //below can be removed later, when we get read rid of deprecated stuff if (annotationEngine.getClass() != new DefaultMockitoConfiguration().getAnnotationEngine().getClass()) { //this means user has his own annotation engine and we have to respect that. //we will do annotation processing the old way so that we are backwards compatible while (clazz != Object.class) { scanDeprecatedWay(annotationEngine, testClass, clazz); clazz = clazz.getSuperclass(); } } //anyway act 'the new' way annotationEngine.process(testClass.getClass(), testClass); } static void scanDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Class> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { processAnnotationDeprecatedWay(annotationEngine, testClass, field); } } @SuppressWarnings("deprecation") static void processAnnotationDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Field field) { boolean alreadyAssigned = false; for(Annotation annotation : field.getAnnotations()) { Object mock = annotationEngine.createMockFor(annotation, field); if (mock != null) { throwIfAlreadyAssigned(field, alreadyAssigned); alreadyAssigned = true; try { new FieldSetter(testClass, field).set(mock); } catch (Exception e) { throw new MockitoException("Problems setting field " + field.getName() + " annotated with " + annotation, e); } } } } static void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) { if (alreadyAssigned) { new Reporter().moreThanOneAnnotationNotAllowed(field.getName()); } } }