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