1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/*
2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Copyright (c) 2007 Mockito contributors
3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This program is made available under the terms of the MIT License.
4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */
5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpackage org.mockito.internal.configuration.injection;
7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.Mockito;
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.Spy;
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.base.MockitoException;
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.MockUtil;
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.reflection.FieldReader;
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.reflection.FieldSetter;
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.reflect.Field;
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.Set;
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport static org.mockito.Mockito.withSettings;
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/**
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Handler for field annotated with @InjectMocks and @Spy.
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson *
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p>
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * The handler assumes that field initialization AND injection already happened.
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * So if the field is still null, then nothing will happen there.
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * </p>
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class SpyOnInjectedFieldsHandler extends MockInjectionStrategy {
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    @Override
31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        FieldReader fieldReader = new FieldReader(fieldOwner, field);
33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        // TODO refoctor : code duplicated in SpyAnnotationEngine
35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if(!fieldReader.isNull() && field.isAnnotationPresent(Spy.class)) {
36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            try {
37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                Object instance = fieldReader.read();
38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                if (new MockUtil().isMock(instance)) {
39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    // A. instance has been spied earlier
40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    // B. protect against multiple use of MockitoAnnotations.initMocks()
41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    Mockito.reset(instance);
42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                } else {
43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    new FieldSetter(fieldOwner, field).set(
44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                        Mockito.mock(instance.getClass(), withSettings()
45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                            .spiedInstance(instance)
46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                            .defaultAnswer(Mockito.CALLS_REAL_METHODS)
47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                            .name(field.getName()))
48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    );
49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                }
50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            } catch (Exception e) {
51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                throw new MockitoException("Problems initiating spied field " + field.getName(), e);
52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return false;
56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson}
58