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.injection; 6 7 import static org.mockito.Mockito.withSettings; 8 9 import java.lang.reflect.Field; 10 import java.util.Set; 11 12 import org.mockito.Mockito; 13 import org.mockito.Spy; 14 import org.mockito.exceptions.base.MockitoException; 15 import org.mockito.internal.configuration.plugins.Plugins; 16 import org.mockito.internal.util.MockUtil; 17 import org.mockito.internal.util.reflection.FieldReader; 18 import org.mockito.plugins.MemberAccessor; 19 20 /** 21 * Handler for field annotated with @InjectMocks and @Spy. 22 * 23 * <p> 24 * The handler assumes that field initialization AND injection already happened. 25 * So if the field is still null, then nothing will happen there. 26 * </p> 27 */ 28 public class SpyOnInjectedFieldsHandler extends MockInjectionStrategy { 29 30 private final MemberAccessor accessor = Plugins.getMemberAccessor(); 31 32 @Override processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates)33 protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) { 34 FieldReader fieldReader = new FieldReader(fieldOwner, field); 35 36 // TODO refactor : code duplicated in SpyAnnotationEngine 37 if (!fieldReader.isNull() && field.isAnnotationPresent(Spy.class)) { 38 try { 39 Object instance = fieldReader.read(); 40 if (MockUtil.isMock(instance)) { 41 // A. instance has been spied earlier 42 // B. protect against multiple use of MockitoAnnotations.openMocks() 43 Mockito.reset(instance); 44 } else { 45 Object mock = 46 Mockito.mock( 47 instance.getClass(), 48 withSettings() 49 .spiedInstance(instance) 50 .defaultAnswer(Mockito.CALLS_REAL_METHODS) 51 .name(field.getName())); 52 accessor.set(field, fieldOwner, mock); 53 } 54 } catch (Exception e) { 55 throw new MockitoException("Problems initiating spied field " + field.getName(), e); 56 } 57 } 58 59 return false; 60 } 61 } 62