/
InjectMocks.java
171 lines (167 loc) · 6.95 KB
/
InjectMocks.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.mockito.junit.MockitoJUnitRunner;
/**
* Mark a field on which injection should be performed.
*
* <ul>
* <li>Allows shorthand mock and spy injection.</li>
* <li>Minimizes repetitive mock and spy injection.</li>
* </ul>
* <p>
* Mockito will try to inject mocks only either by constructor injection,
* setter injection, or property injection in order and as described below.
* If any of the following strategy fail, then Mockito <strong>won't report failure</strong>;
* i.e. you will have to provide dependencies yourself.
* <ol>
* <li><strong>Constructor injection</strong>; the biggest constructor is chosen,
* then arguments are resolved with mocks declared in the test only. If the object is successfully created
* with the constructor, then <strong>Mockito won't try the other strategies</strong>. Mockito has decided to no
* corrupt an object if it has a parametered constructor.
* <p><u>Note:</u> If arguments can not be found, then null is passed.
* If non-mockable types are wanted, then constructor injection won't happen.
* In these cases, you will have to satisfy dependencies yourself.</p></li>
*
* <li><strong>Property setter injection</strong>; mocks will first be resolved by type (if a single type match
* injection will happen regardless of the name),
* then, if there is several property of the same type, by the match of the property name and the mock name.
* <p><u>Note 1:</u> If you have properties with the same type (or same erasure), it's better to name all @Mock
* annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.</p>
* <p><u>Note 2:</u> If @InjectMocks instance wasn't initialized before and has a no-arg constructor,
* then it will be initialized with this constructor.</p></li>
*
* <li><strong>Field injection</strong>; mocks will first be resolved by type (if a single type match
* injection will happen regardless of the name),
* then, if there is several property of the same type, by the match of the field name and the mock name.
* <p><u>Note 1:</u> If you have fields with the same type (or same erasure), it's better to name all @Mock
* annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.</p>
* <p><u>Note 2:</u> If @InjectMocks instance wasn't initialized before and have a no-arg constructor,
* then it will be initialized with this constructor.</p></li>
* </ol>
* </p>
*
* <p>
* Example:
* <pre class="code"><code class="java">
* public class ArticleManagerTest extends SampleBaseTestCase {
*
* @Mock private ArticleCalculator calculator;
* @Mock(name = "database") private ArticleDatabase dbMock; // note the mock name attribute
* @Spy private UserProvider userProvider = new ConsumerUserProvider();
*
* @InjectMocks private ArticleManager manager;
*
* @Test public void shouldDoSomething() {
* manager.initiateArticle();
* verify(database).addListener(any(ArticleListener.class));
* }
* }
*
* public class SampleBaseTestCase {
*
* private AutoCloseable closeable;
*
* @Before public void openMocks() {
* closeable = MockitoAnnotations.openMocks(this);
* }
*
* @After public void releaseMocks() throws Exception {
* closeable.close();
* }
* }
* </code></pre>
* </p>
*
* <p>
* In the above example the field <code>ArticleManager</code> annotated with <code>@InjectMocks</code> can have
* a parameterized constructor only or a no-arg constructor only, or both.
* All these constructors can be package protected, protected or private, however
* <u>Mockito cannot instantiate inner classes, local classes, abstract classes and of course interfaces.</u>
* <u>Beware of private nested static classes too.</u>
*
* <p>The same stands for setters or fields, they can be declared with private
* visibility, Mockito will see them through reflection.
* However fields that are static or final will be ignored.</p>
*
* <p>So on the field that needs injection, for example constructor injection will happen here:</p>
* <pre class="code"><code class="java">
* public class ArticleManager {
* ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
* // parameterized constructor
* }
* }
* </code></pre>
*
* <p>Property setter injection will happen here:</p>
* <pre class="code"><code class="java">
* public class ArticleManager {
* // no-arg constructor
* ArticleManager() { }
*
* // setter
* void setDatabase(ArticleDatabase database) { }
*
* // setter
* void setCalculator(ArticleCalculator calculator) { }
* }
* </code></pre>
*
* <p>Field injection will be used here:</p>
* <pre class="code"><code class="java">
* public class ArticleManager {
* private ArticleDatabase database;
* private ArticleCalculator calculator;
* }
* </code></pre>
* </p>
*
* <p>And finally, no injection will happen on the type in this case:</p>
* <pre class="code"><code class="java">
* public class ArticleManager {
* private ArticleDatabase database;
* private ArticleCalculator calculator;
*
* ArticleManager(ArticleObserver observer, boolean flag) {
* // observer is not declared in the test above.
* // flag is not mockable anyway
* }
* }
* </code></pre>
* </p>
*
*
* <p>
* Again, note that @InjectMocks will only inject mocks/spies created using the @Spy or @Mock annotation.
* </p>
*
* <p>
* <strong><code>MockitoAnnotations.openMocks(this)</code></strong> method has to be called to initialize annotated objects.
* In above example, <code>openMocks()</code> is called in @Before (JUnit4) method of test's base class.
* For JUnit3 <code>openMocks()</code> can go to <code>setup()</code> method of a base class.
* <strong>Instead</strong> you can also put openMocks() in your JUnit runner (@RunWith) or use the built-in
* {@link MockitoJUnitRunner}. Also, make sure to release any mocks after disposing your test class with a corresponding hook.
* </p>
*
* <p>
* Mockito is not an dependency injection framework, don't expect this shorthand utility to inject a complex graph of objects
* be it mocks/spies or real objects.
* </p>
*
* @see Mock
* @see Spy
* @see MockitoAnnotations#openMocks(Object)
* @see MockitoJUnitRunner
* @since 1.8.3
*/
@Documented
@Target(FIELD)
@Retention(RUNTIME)
public @interface InjectMocks {}