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 java.lang.reflect.Field;
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.Collections;
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.HashSet;
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.Set;
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport static org.mockito.internal.util.Checks.checkItemsNotNull;
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport static org.mockito.internal.util.Checks.checkNotNull;
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/**
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Internal injection configuration utility.
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson *
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p>
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Allow the user of this class to configure the way the injection of mocks will happen.
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * </p>
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson *
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class MockInjection {
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    /**
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * Create a new configuration setup for a field
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     *
30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     *
31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @param field Field needing mock injection
32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @param ofInstance Instance owning the <code>field</code>
33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @return New configuration builder
34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     */
35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public static OngoingMockInjection onField(Field field, Object ofInstance) {
36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return new OngoingMockInjection(field, ofInstance);
37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    /**
40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * Create a new configuration setup for fields
41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     *
42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     *
43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @param fields Fields needing mock injection
44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @param ofInstance Instance owning the <code>field</code>
45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @return New configuration builder
46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     */
47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public static OngoingMockInjection onFields(Set<Field> fields, Object ofInstance) {
48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return new OngoingMockInjection(fields, ofInstance);
49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    /**
52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * Ongoing configuration of the mock injector.
53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     */
54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public static class OngoingMockInjection {
55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private Set<Field> fields = new HashSet<Field>();
56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private Set<Object> mocks = newMockSafeHashSet();
57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private Object fieldOwner;
58e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private MockInjectionStrategy injectionStrategies = MockInjectionStrategy.nop();
59e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private MockInjectionStrategy postInjectionStrategies = MockInjectionStrategy.nop();
60e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
61e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private OngoingMockInjection(Field field, Object fieldOwner) {
62e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            this(Collections.singleton(field), fieldOwner);
63e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
64e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
65e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        private OngoingMockInjection(Set<Field> fields, Object fieldOwner) {
66e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            this.fieldOwner = checkNotNull(fieldOwner, "fieldOwner");
67e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            this.fields.addAll(checkItemsNotNull(fields, "fields"));
68e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
69e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
70e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        public OngoingMockInjection withMocks(Set<Object> mocks) {
71e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            this.mocks.addAll(checkNotNull(mocks, "mocks"));
72e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return this;
73e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
74e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
75e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        public OngoingMockInjection tryConstructorInjection() {
76e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            injectionStrategies.thenTry(new ConstructorInjection());
77e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return this;
78e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
79e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
80e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        public OngoingMockInjection tryPropertyOrFieldInjection() {
81e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            injectionStrategies.thenTry(new PropertyAndSetterInjection());
82e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return this;
83e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
84e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
85e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        public OngoingMockInjection handleSpyAnnotation() {
86e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            postInjectionStrategies.thenTry(new SpyOnInjectedFieldsHandler());
87e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return this;
88e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
89e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
90e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        public void apply() {
91e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            for (Field field : fields) {
92e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                injectionStrategies.process(field, fieldOwner, mocks);
93e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                postInjectionStrategies.process(field, fieldOwner, mocks);
94e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
95e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
96e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
97e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson}
98