• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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