View Javadoc
1   package mockit;
2   
3   import static java.util.Collections.singletonList;
4   
5   import static org.junit.jupiter.api.Assertions.assertEquals;
6   import static org.junit.jupiter.api.Assertions.assertNotNull;
7   import static org.junit.jupiter.api.Assertions.assertNotSame;
8   import static org.junit.jupiter.api.Assertions.assertNull;
9   import static org.junit.jupiter.api.Assertions.assertSame;
10  import static org.junit.jupiter.api.Assertions.assertTrue;
11  
12  import java.util.ArrayList;
13  import java.util.List;
14  import java.util.concurrent.Callable;
15  
16  import javax.inject.Inject;
17  import javax.inject.Provider;
18  import javax.inject.Singleton;
19  
20  import org.junit.jupiter.api.BeforeEach;
21  import org.junit.jupiter.api.Test;
22  
23  /**
24   * The Class StandardDITest.
25   */
26  final class StandardDITest {
27  
28      /**
29       * The Class TestedClass.
30       */
31      public static class TestedClass {
32  
33          /** The global action. */
34          @Inject
35          static Runnable globalAction;
36  
37          /** The collaborator. */
38          private final Collaborator collaborator;
39  
40          /** The collaborator 1. */
41          @Inject
42          private Collaborator collaborator1;
43  
44          /** The collaborator 2. */
45          Collaborator collaborator2;
46  
47          /** The some value. */
48          @Inject
49          int someValue;
50  
51          /** The another value. */
52          @Inject
53          private int anotherValue;
54  
55          /** The non annotated field. */
56          String nonAnnotatedField;
57  
58          /** The non annotated generic field. */
59          Callable<String> nonAnnotatedGenericField;
60  
61          /**
62           * Instantiates a new tested class.
63           *
64           * @param collaborator
65           *            the collaborator
66           */
67          @Inject
68          public TestedClass(Collaborator collaborator) {
69              this.collaborator = collaborator;
70          }
71  
72          /**
73           * Instantiates a new tested class.
74           *
75           * @param collaborator
76           *            the collaborator
77           * @param anotherValue
78           *            the another value
79           */
80          @SuppressWarnings("unused")
81          public TestedClass(Collaborator collaborator, int anotherValue) {
82              throw new RuntimeException("Must not occur");
83          }
84      }
85  
86      /**
87       * The Class Collaborator.
88       */
89      static class Collaborator {
90          /** The b. */
91          boolean b = true;
92      }
93  
94      /** The tested 1. */
95      @Tested
96      TestedClass tested1;
97  
98      /** The collaborator. */
99      @Injectable
100     Collaborator collaborator; // for constructor injection
101 
102     /** The collaborator 1. */
103     @Injectable
104     Collaborator collaborator1; // for field injection
105 
106     /** The some value. */
107     @Injectable("123")
108     int someValue;
109 
110     /** The another value. */
111     @Injectable
112     final int anotherValue = 45;
113 
114     /** The callable. */
115     @Injectable
116     Callable<String> callable;
117 
118     /**
119      * The Class TestedClassWithNoAnnotatedConstructor.
120      */
121     static final class TestedClassWithNoAnnotatedConstructor {
122 
123         /** The value. */
124         @Inject
125         int value;
126 
127         /** The a text. */
128         @Inject
129         String aText;
130 
131         /** The another text. */
132         String anotherText;
133     }
134 
135     /** The tested 2. */
136     @Tested
137     TestedClassWithNoAnnotatedConstructor tested2;
138 
139     /** The a text. */
140     @Injectable
141     final String aText = "Abc";
142 
143     /**
144      * The Class TestedClassWithInjectOnConstructorOnly.
145      */
146     public static class TestedClassWithInjectOnConstructorOnly {
147 
148         /** The name. */
149         String name;
150 
151         /**
152          * Instantiates a new tested class with inject on constructor only.
153          */
154         @Inject
155         public TestedClassWithInjectOnConstructorOnly() {
156         }
157     }
158 
159     /** The tested 3. */
160     @Tested
161     TestedClassWithInjectOnConstructorOnly tested3;
162 
163     /**
164      * Invoke inject annotated constructor only.
165      */
166     @Test
167     void invokeInjectAnnotatedConstructorOnly() {
168         assertSame(collaborator, tested1.collaborator);
169         assertSame(collaborator1, tested1.collaborator1);
170         assertNull(tested1.collaborator2);
171         assertEquals(123, tested1.someValue);
172         assertEquals(45, tested1.anotherValue);
173 
174         assertEquals(123, tested2.value);
175     }
176 
177     /**
178      * Assign inject annotated fields and also non annotated ones.
179      *
180      * @param collaborator2
181      *            the collaborator 2
182      * @param notToBeUsed
183      *            the not to be used
184      */
185     @Test
186     void assignInjectAnnotatedFieldsAndAlsoNonAnnotatedOnes(@Injectable Collaborator collaborator2,
187             @Injectable("67") int notToBeUsed) {
188         assertSame(collaborator, tested1.collaborator);
189         assertSame(collaborator1, tested1.collaborator1);
190         assertSame(collaborator2, tested1.collaborator2);
191         assertEquals(123, tested1.someValue);
192         assertEquals(45, tested1.anotherValue);
193 
194         assertEquals(123, tested2.value);
195     }
196 
197     /**
198      * Assign annotated field even if tested class has no annotated constructor.
199      *
200      * @param value
201      *            the value
202      */
203     @Test
204     void assignAnnotatedFieldEvenIfTestedClassHasNoAnnotatedConstructor(@Injectable("123") int value) {
205         assertEquals(123, tested2.value);
206     }
207 
208     /** The action. */
209     @Injectable
210     Runnable action;
211 
212     /**
213      * Assign annotated static field during field injection.
214      */
215     @Test
216     void assignAnnotatedStaticFieldDuringFieldInjection() {
217         assertSame(action, TestedClass.globalAction);
218     }
219 
220     /**
221      * Consider annotated and non annotated fields for injection.
222      *
223      * @param text2
224      *            the text 2
225      */
226     @Test
227     void considerAnnotatedAndNonAnnotatedFieldsForInjection(@Injectable("XY") String text2) {
228         assertEquals(aText, tested2.aText);
229         assertNull(tested2.anotherText);
230         assertEquals(aText, tested3.name);
231     }
232 
233     /**
234      * The Class TestedClassWithProviders.
235      */
236     static final class TestedClassWithProviders {
237 
238         /** The port. */
239         final int port;
240 
241         /** The collaborator. */
242         final Collaborator collaborator;
243 
244         /** The user. */
245         @Inject
246         Provider<String> user;
247 
248         /** The password. */
249         @Inject
250         Provider<String> password;
251 
252         /**
253          * Instantiates a new tested class with providers.
254          *
255          * @param port
256          *            the port
257          * @param collaborator
258          *            the collaborator
259          */
260         @Inject
261         TestedClassWithProviders(Provider<Integer> port, Collaborator collaborator) {
262             this.port = port.get();
263             this.collaborator = collaborator;
264         }
265     }
266 
267     /** The tested 4. */
268     @Tested
269     TestedClassWithProviders tested4;
270 
271     /** The port number. */
272     @Injectable
273     Integer portNumber = 4567;
274 
275     /** The user. */
276     @Injectable
277     String user = "John";
278 
279     /** The password. */
280     @Injectable
281     String password = "123";
282 
283     /**
284      * Support provider fields and parameters.
285      */
286     @Test
287     void supportProviderFieldsAndParameters() {
288         assertEquals(portNumber.intValue(), tested4.port);
289         assertSame(collaborator, tested4.collaborator);
290         assertEquals(user, tested4.user.get());
291         assertEquals(password, tested4.password.get());
292     }
293 
294     /**
295      * The Class TestedClassWithVarargsParameterForProviders.
296      */
297     static final class TestedClassWithVarargsParameterForProviders {
298 
299         /** The collaborator 1. */
300         final Collaborator collaborator1;
301 
302         /** The collaborator 2. */
303         final Collaborator collaborator2;
304 
305         /** The optional collaborators. */
306         final List<Collaborator> optionalCollaborators = new ArrayList<>();
307 
308         /** The name provider. */
309         @Inject
310         Provider<String> nameProvider;
311 
312         /**
313          * Instantiates a new tested class with varargs parameter for providers.
314          *
315          * @param collaborators
316          *            the collaborators
317          */
318         @SuppressWarnings({ "unchecked", "VariableArgumentMethod" })
319         @Inject
320         TestedClassWithVarargsParameterForProviders(Provider<Collaborator>... collaborators) {
321             int n = collaborators.length;
322             assertTrue(n > 1);
323 
324             collaborator1 = collaborators[0].get();
325             assertSame(collaborator1, collaborators[0].get()); // default (singleton)
326 
327             collaborator2 = collaborators[2].get();
328             assertNull(collaborators[2].get()); // recorded
329 
330             if (n > 3) {
331                 Collaborator col = collaborators[3].get();
332                 optionalCollaborators.add(col);
333             }
334         }
335     }
336 
337     /** The tested 5. */
338     @Tested
339     TestedClassWithVarargsParameterForProviders tested5;
340 
341     /** The collaborator provider. */
342     @Injectable
343     Provider<Collaborator> collaboratorProvider;
344 
345     /** The col 3. */
346     @Injectable
347     Collaborator col3;
348 
349     /**
350      * Configure provider used by constructor of tested class.
351      */
352     @BeforeEach
353     void configureProviderUsedByConstructorOfTestedClass() {
354         new Expectations() {
355             {
356                 Collaborator[] collaborators = { col3, null };
357                 collaboratorProvider.get();
358                 result = collaborators;
359             }
360         };
361     }
362 
363     /**
364      * Support varargs parameter with providers.
365      *
366      * @param nameProvider
367      *            the name provider
368      */
369     @Test
370     void supportVarargsParameterWithProviders(@Injectable final Provider<String> nameProvider) {
371         final String[] names = { "John", "Mary" };
372         new Expectations() {
373             {
374                 nameProvider.get();
375                 result = names;
376             }
377         };
378 
379         assertSame(collaborator, tested5.collaborator1);
380         assertNotNull(tested5.collaborator2);
381         assertNotSame(tested5.collaborator1, tested5.collaborator2);
382         assertEquals(singletonList(col3), tested5.optionalCollaborators);
383 
384         assertEquals(names[0], tested5.nameProvider.get());
385         assertEquals(names[1], tested5.nameProvider.get());
386     }
387 
388     /**
389      * Fields not annotated with known DI annotations should still be injected.
390      */
391     @Test
392     void fieldsNotAnnotatedWithKnownDIAnnotationsShouldStillBeInjected() {
393         assertEquals("Abc", tested1.nonAnnotatedField);
394         assertSame(callable, tested1.nonAnnotatedGenericField);
395     }
396 
397     /**
398      * The Class DependencyToBeProvided.
399      */
400     public static final class DependencyToBeProvided {
401     }
402 
403     /**
404      * The Class TestedClassWithProvider.
405      */
406     public static final class TestedClassWithProvider {
407         /** The provider. */
408         @Inject
409         Provider<DependencyToBeProvided> provider;
410     }
411 
412     /** The tested 6. */
413     @Tested(fullyInitialized = true)
414     TestedClassWithProvider tested6;
415 
416     /**
417      * Instantiate class with dependency from standard provider.
418      */
419     @Test
420     void instantiateClassWithDependencyFromStandardProvider() {
421         DependencyToBeProvided providedDependency1 = tested6.provider.get();
422         DependencyToBeProvided providedDependency2 = tested6.provider.get();
423         assertNotNull(providedDependency1);
424         assertNotNull(providedDependency2);
425         assertNotSame(providedDependency1, providedDependency2);
426     }
427 
428     /**
429      * The Class SingletonDependencyToBeProvided.
430      */
431     @Singleton
432     public static final class SingletonDependencyToBeProvided {
433     }
434 
435     /**
436      * The Class TestedClassWithSingletonProvider.
437      */
438     public static final class TestedClassWithSingletonProvider {
439         /** The provider. */
440         @Inject
441         Provider<SingletonDependencyToBeProvided> provider;
442     }
443 
444     /** The tested 7. */
445     @Tested(fullyInitialized = true)
446     TestedClassWithSingletonProvider tested7;
447 
448     /**
449      * Instantiate class with singleton dependency from standard provider.
450      */
451     @Test
452     void instantiateClassWithSingletonDependencyFromStandardProvider() {
453         SingletonDependencyToBeProvided providedDependency1 = tested7.provider.get();
454         SingletonDependencyToBeProvided providedDependency2 = tested7.provider.get();
455         assertNotNull(providedDependency1);
456         assertNotNull(providedDependency2);
457         assertSame(providedDependency1, providedDependency2);
458     }
459 }