1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 6 package org.mockito.internal.configuration.injection; 7 8 import org.mockito.Mockito; 9 import org.mockito.Spy; 10 import org.mockito.exceptions.base.MockitoException; 11 import org.mockito.internal.util.MockUtil; 12 import org.mockito.internal.util.reflection.FieldReader; 13 14 import java.lang.reflect.Field; 15 import java.util.Set; 16 17 import static org.mockito.Mockito.withSettings; 18 import static org.mockito.internal.util.reflection.FieldSetter.setField; 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 @Override processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates)31 protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) { 32 FieldReader fieldReader = new FieldReader(fieldOwner, field); 33 34 // TODO refoctor : code duplicated in SpyAnnotationEngine 35 if(!fieldReader.isNull() && field.isAnnotationPresent(Spy.class)) { 36 try { 37 Object instance = fieldReader.read(); 38 if (MockUtil.isMock(instance)) { 39 // A. instance has been spied earlier 40 // B. protect against multiple use of MockitoAnnotations.initMocks() 41 Mockito.reset(instance); 42 } else { 43 Object mock = Mockito.mock(instance.getClass(), withSettings() 44 .spiedInstance(instance) 45 .defaultAnswer(Mockito.CALLS_REAL_METHODS) 46 .name(field.getName())); 47 setField(fieldOwner, field, mock); 48 } 49 } catch (Exception e) { 50 throw new MockitoException("Problems initiating spied field " + field.getName(), e); 51 } 52 } 53 54 return false; 55 } 56 } 57