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.injection.scanner; 6 7import org.mockito.Mock; 8import org.mockito.MockitoAnnotations; 9import org.mockito.Spy; 10import org.mockito.internal.util.MockUtil; 11import org.mockito.internal.util.reflection.FieldReader; 12 13import java.lang.reflect.Field; 14import java.util.Set; 15 16import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet; 17 18/** 19 * Scan mocks, and prepare them if needed. 20 */ 21public class MockScanner { 22 private MockUtil mockUtil = new MockUtil(); 23 private final Object instance; 24 private final Class<?> clazz; 25 26 /** 27 * Creates a MockScanner. 28 * 29 * @param instance The test instance 30 * @param clazz The class in the type hierarchy of this instance. 31 */ 32 public MockScanner(Object instance, Class<?> clazz) { 33 this.instance = instance; 34 this.clazz = clazz; 35 } 36 37 /** 38 * Add the scanned and prepared mock instance to the given collection. 39 * 40 * <p> 41 * The preparation of mocks consists only in defining a MockName if not already set. 42 * </p> 43 * 44 * @param mocks Set of mocks 45 */ 46 public void addPreparedMocks(Set<Object> mocks) { 47 mocks.addAll(scan()); 48 } 49 50 /** 51 * Scan and prepare mocks for the given <code>testClassInstance</code> and <code>clazz</code> in the type hierarchy. 52 * 53 * @return A prepared set of mock 54 */ 55 private Set<Object> scan() { 56 Set<Object> mocks = newMockSafeHashSet(); 57 for (Field field : clazz.getDeclaredFields()) { 58 // mock or spies only 59 FieldReader fieldReader = new FieldReader(instance, field); 60 61 Object mockInstance = preparedMock(fieldReader.read(), field); 62 if (mockInstance != null) { 63 mocks.add(mockInstance); 64 } 65 } 66 return mocks; 67 } 68 69 private Object preparedMock(Object instance, Field field) { 70 if (isAnnotatedByMockOrSpy(field)) { 71 return instance; 72 } else if (isMockOrSpy(instance)) { 73 mockUtil.maybeRedefineMockName(instance, field.getName()); 74 return instance; 75 } 76 return null; 77 } 78 79 private boolean isAnnotatedByMockOrSpy(Field field) { 80 return null != field.getAnnotation(Spy.class) 81 || null != field.getAnnotation(Mock.class) 82 || null != field.getAnnotation(MockitoAnnotations.Mock.class); 83 } 84 85 private boolean isMockOrSpy(Object instance) { 86 return mockUtil.isMock(instance) 87 || mockUtil.isSpy(instance); 88 } 89} 90