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 import org.mockito.internal.util.reflection.FieldSetter;
14 
15 import java.lang.reflect.Field;
16 import java.util.Set;
17 
18 import static org.mockito.Mockito.withSettings;
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 (new 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                     new FieldSetter(fieldOwner, field).set(
44                         Mockito.mock(instance.getClass(), withSettings()
45                             .spiedInstance(instance)
46                             .defaultAnswer(Mockito.CALLS_REAL_METHODS)
47                             .name(field.getName()))
48                     );
49                 }
50             } catch (Exception e) {
51                 throw new MockitoException("Problems initiating spied field " + field.getName(), e);
52             }
53         }
54 
55         return false;
56     }
57 }
58