1/* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5package org.mockito.internal.configuration; 6 7import org.mockito.*; 8import org.mockito.configuration.AnnotationEngine; 9import org.mockito.internal.configuration.injection.scanner.InjectMocksScanner; 10import org.mockito.internal.configuration.injection.scanner.MockScanner; 11 12import java.lang.annotation.Annotation; 13import java.lang.reflect.Field; 14import java.util.HashSet; 15import java.util.Set; 16 17import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet; 18 19/** 20 * See {@link MockitoAnnotations} 21 */ 22@SuppressWarnings({"deprecation", "unchecked"}) 23public class InjectingAnnotationEngine implements AnnotationEngine { 24 private AnnotationEngine delegate = new DefaultAnnotationEngine(); 25 private AnnotationEngine spyAnnotationEngine = new SpyAnnotationEngine(); 26 27 /*** 28 * Create a mock using {@link DefaultAnnotationEngine} 29 * 30 * @see org.mockito.internal.configuration.DefaultAnnotationEngine 31 * @see org.mockito.configuration.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field) 32 */ 33 @Deprecated 34 public Object createMockFor(Annotation annotation, Field field) { 35 return delegate.createMockFor(annotation, field); 36 } 37 38 /** 39 * Process the fields of the test instance and create Mocks, Spies, Captors and inject them on fields 40 * annotated @InjectMocks. 41 * 42 * <p> 43 * This code process the test class and the super classes. 44 * <ol> 45 * <li>First create Mocks, Spies, Captors.</li> 46 * <li>Then try to inject them.</li> 47 * </ol> 48 * 49 * @param clazz Not used 50 * @param testInstance The instance of the test, should not be null. 51 * 52 * @see org.mockito.configuration.AnnotationEngine#process(Class, Object) 53 */ 54 public void process(Class<?> clazz, Object testInstance) { 55 processIndependentAnnotations(testInstance.getClass(), testInstance); 56 processInjectMocks(testInstance.getClass(), testInstance); 57 } 58 59 private void processInjectMocks(final Class<?> clazz, final Object testInstance) { 60 Class<?> classContext = clazz; 61 while (classContext != Object.class) { 62 injectMocks(testInstance); 63 classContext = classContext.getSuperclass(); 64 } 65 } 66 67 private void processIndependentAnnotations(final Class<?> clazz, final Object testInstance) { 68 Class<?> classContext = clazz; 69 while (classContext != Object.class) { 70 //this will create @Mocks, @Captors, etc: 71 delegate.process(classContext, testInstance); 72 //this will create @Spies: 73 spyAnnotationEngine.process(classContext, testInstance); 74 75 classContext = classContext.getSuperclass(); 76 } 77 } 78 79 80 /** 81 * Initializes mock/spies dependencies for objects annotated with 82 * @InjectMocks for given testClassInstance. 83 * <p> 84 * See examples in javadoc for {@link MockitoAnnotations} class. 85 * 86 * @param testClassInstance 87 * Test class, usually <code>this</code> 88 */ 89 public void injectMocks(final Object testClassInstance) { 90 Class<?> clazz = testClassInstance.getClass(); 91 Set<Field> mockDependentFields = new HashSet<Field>(); 92 Set<Object> mocks = newMockSafeHashSet(); 93 94 while (clazz != Object.class) { 95 new InjectMocksScanner(clazz).addTo(mockDependentFields); 96 new MockScanner(testClassInstance, clazz).addPreparedMocks(mocks); 97 clazz = clazz.getSuperclass(); 98 } 99 100 new DefaultInjectionEngine().injectMocksOnFields(mockDependentFields, mocks, testClassInstance); 101 } 102 103} 104