View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit;
7   
8   import static org.junit.jupiter.api.Assertions.assertEquals;
9   import static org.junit.jupiter.api.Assertions.assertNotNull;
10  import static org.junit.jupiter.api.Assertions.assertNull;
11  import static org.junit.jupiter.api.Assertions.assertSame;
12  import static org.junit.jupiter.api.Assertions.assertTrue;
13  
14  import jakarta.persistence.Entity;
15  import jakarta.persistence.EntityManager;
16  import jakarta.persistence.EntityManagerFactory;
17  
18  import java.lang.annotation.ElementType;
19  import java.lang.annotation.Retention;
20  import java.lang.annotation.RetentionPolicy;
21  import java.lang.annotation.Target;
22  
23  import javax.sql.DataSource;
24  
25  import mockit.integration.junit5.JMockitExtension;
26  
27  import org.junit.jupiter.api.MethodOrderer.MethodName;
28  import org.junit.jupiter.api.Test;
29  import org.junit.jupiter.api.TestMethodOrder;
30  import org.junit.jupiter.api.extension.ExtendWith;
31  
32  /**
33   * The Class TestedClassWithFullDITest.
34   */
35  @ExtendWith(JMockitExtension.class)
36  @TestMethodOrder(MethodName.class)
37  class TestedClassWithFullDITest {
38  
39      /**
40       * The Class TestedClass.
41       */
42      public static class TestedClass {
43  
44          /** The dependency to be mocked. */
45          Runnable dependencyToBeMocked;
46  
47          /** The dependency 2. */
48          FirstLevelDependency dependency2;
49  
50          /** The dependency 3. */
51          FirstLevelDependency dependency3;
52  
53          /** The common dependency. */
54          CommonDependency commonDependency;
55  
56          /** The name. */
57          String name;
58  
59          /** The description. */
60          StringBuilder description;
61  
62          /** The number. */
63          final Integer number = null;
64  
65          /** The flag. */
66          boolean flag = true;
67  
68          /** The thread state. */
69          Thread.State threadState;
70  
71          /** The sub obj. */
72          AnotherTestedClass subObj;
73  
74          /** The sub obj 2. */
75          YetAnotherTestedClass subObj2;
76  
77          /** The not to be injected. */
78          volatile CommonDependency notToBeInjected;
79      }
80  
81      /**
82       * The Class FirstLevelDependency.
83       */
84      public static class FirstLevelDependency {
85  
86          /** The first level id. */
87          String firstLevelId;
88  
89          /** The dependency. */
90          SecondLevelDependency dependency;
91  
92          /** The common dependency. */
93          CommonDependency commonDependency;
94  
95          /** The dependency to be mocked. */
96          Runnable dependencyToBeMocked;
97      }
98  
99      /**
100      * The Class SecondLevelDependency.
101      */
102     public static class SecondLevelDependency {
103         /** The common dependency. */
104         CommonDependency commonDependency;
105     }
106 
107     /**
108      * The Class CommonDependency.
109      */
110     public static class CommonDependency {
111     }
112 
113     /**
114      * The Interface IntegrationTested.
115      */
116     @Tested(fullyInitialized = true)
117     @Retention(RetentionPolicy.RUNTIME)
118     @Target(ElementType.FIELD)
119     public @interface IntegrationTested {
120     }
121 
122     /**
123      * The Class YetAnotherTestedClass.
124      */
125     public static class YetAnotherTestedClass {
126     }
127 
128     /** The tested 3. */
129     @IntegrationTested
130     YetAnotherTestedClass tested3;
131 
132     /** The tested. */
133     @IntegrationTested
134     TestedClass tested;
135 
136     /** The mocked dependency. */
137     @Injectable
138     Runnable mockedDependency;
139 
140     /**
141      * Use fully initialized tested object with no injectable for first level dependency.
142      */
143     @Test
144     void useFullyInitializedTestedObjectWithNoInjectableForFirstLevelDependency() {
145         assertNull(tested.name);
146         assertSame(tested.commonDependency, tested.dependency2.dependency.commonDependency);
147         assertNull(tested.notToBeInjected);
148     }
149 
150     /**
151      * Use fully initialized tested object with value for first level dependency.
152      *
153      * @param id
154      *            the id
155      */
156     @Test
157     void useFullyInitializedTestedObjectWithValueForFirstLevelDependency(@Injectable("test") String id) {
158         assertEquals("test", tested.name);
159         assertNull(tested.description);
160         assertNull(tested.number);
161         assertTrue(tested.flag);
162         assertNull(tested.threadState);
163         assertSame(mockedDependency, tested.dependencyToBeMocked);
164         assertNotNull(tested.dependency2);
165         assertEquals("test", tested.dependency2.firstLevelId);
166         assertSame(tested.dependency2, tested.dependency3);
167         assertNotNull(tested.commonDependency);
168         assertNotNull(tested.dependency2.dependency);
169         assertSame(tested.dependency2.dependency, tested.dependency3.dependency);
170         assertSame(tested.commonDependency, tested.dependency2.commonDependency);
171         assertSame(tested.commonDependency, tested.dependency3.commonDependency);
172         assertSame(tested.commonDependency, tested.dependency2.dependency.commonDependency);
173         assertSame(mockedDependency, tested.dependency2.dependencyToBeMocked);
174         assertSame(mockedDependency, tested.dependency3.dependencyToBeMocked);
175     }
176 
177     /**
178      * The Class AnotherTestedClass.
179      */
180     public static class AnotherTestedClass {
181         /** The sub obj. */
182         YetAnotherTestedClass subObj;
183     }
184 
185     /** The tested 2. */
186     @IntegrationTested
187     AnotherTestedClass tested2;
188 
189     /**
190      * Verify other tested objects get injected into first one.
191      */
192     @Test
193     void verifyOtherTestedObjectsGetInjectedIntoFirstOne() {
194         assertSame(tested2, tested.subObj);
195         assertSame(tested3, tested.subObj2);
196         assertSame(tested3, tested.subObj.subObj);
197     }
198 
199     /** The concrete dependency. */
200     @Tested
201     DependencyImpl concreteDependency;
202 
203     /** The tested 4. */
204     @IntegrationTested
205     ClassWithDependencyOfAbstractType tested4;
206 
207     /**
208      * The Interface Dependency.
209      */
210     public interface Dependency {
211     }
212 
213     /**
214      * The Class DependencyImpl.
215      */
216     static class DependencyImpl implements Dependency {
217     }
218 
219     /**
220      * The Class ClassWithDependencyOfAbstractType.
221      */
222     static class ClassWithDependencyOfAbstractType {
223         /** The dependency. */
224         Dependency dependency;
225     }
226 
227     /**
228      * Use tested object of subtype for abstract dependency type in another tested object.
229      */
230     @Test
231     void useTestedObjectOfSubtypeForAbstractDependencyTypeInAnotherTestedObject() {
232         assertSame(concreteDependency, tested4.dependency);
233     }
234 
235     /**
236      * The Class A.
237      */
238     static class A {
239         /** The b 1. */
240         B b1;
241     }
242 
243     /**
244      * The Class B.
245      */
246     static class B {
247         /** The b 2. */
248         B b2;
249     }
250 
251     /** The a. */
252     @Tested(fullyInitialized = true)
253     A a;
254 
255     /**
256      * Instantiate class dependent on another having field of its own type.
257      */
258     @Test
259     void instantiateClassDependentOnAnotherHavingFieldOfItsOwnType() {
260         B b1 = a.b1;
261         assertNotNull(b1);
262 
263         B b2 = b1.b2;
264         assertNotNull(b2);
265         assertSame(b1, b2);
266     }
267 
268     /**
269      * The Class Person.
270      */
271     @Entity
272     static class Person {
273     }
274 
275     /**
276      * The Class ClassWithJPAEntityField.
277      */
278     static class ClassWithJPAEntityField {
279         /** The person. */
280         Person person;
281     }
282 
283     /**
284      * Instantiate class with JPA entity field.
285      *
286      * @param tested5
287      *            the tested 5
288      */
289     @Test
290     void instantiateClassWithJPAEntityField(@Tested(fullyInitialized = true) ClassWithJPAEntityField tested5) {
291         assertNull(tested5.person);
292     }
293 
294     /**
295      * The Class ClassWithDataSourceField.
296      */
297     static class ClassWithDataSourceField {
298         /** The ds. */
299         DataSource ds;
300     }
301 
302     /**
303      * Instantiate class with non annotated data source field.
304      *
305      * @param tested5
306      *            the tested 5
307      */
308     @Test
309     void instantiateClassWithNonAnnotatedDataSourceField(
310             @Tested(fullyInitialized = true) ClassWithDataSourceField tested5) {
311         assertNull(tested5.ds);
312     }
313 
314     /**
315      * The Class ClassWithJPAFields.
316      */
317     static class ClassWithJPAFields {
318         /** The em factory. */
319         EntityManagerFactory emFactory;
320         /** The em. */
321         EntityManager em;
322     }
323 
324     /**
325      * Instantiate class with non annotated JPA fields.
326      *
327      * @param tested6
328      *            the tested 6
329      */
330     @Test
331     void instantiateClassWithNonAnnotatedJPAFields(@Tested(fullyInitialized = true) ClassWithJPAFields tested6) {
332         // If an EntityManagerFactory was created for a previous test, then it got stored in the global dependency
333         // cache, which lasts
334         // until the end of the test run; therefore, the assertion needs to allow for that.
335         assertTrue(tested6.emFactory == null
336                 || tested6.emFactory.getClass().getName().contains("FakeEntityManagerFactory"));
337         assertNull(tested6.em);
338     }
339 
340     /**
341      * The Class ClassWithUnsatisfiableConstructor.
342      */
343     static class ClassWithUnsatisfiableConstructor {
344         /**
345          * Instantiates a new class with unsatisfiable constructor.
346          *
347          * @param someValue
348          *            the some value
349          */
350         ClassWithUnsatisfiableConstructor(@SuppressWarnings("unused") int someValue) {
351         }
352     }
353 
354     /**
355      * The Class ClassWithFieldToInject.
356      */
357     static class ClassWithFieldToInject {
358         /** The dependency. */
359         ClassWithUnsatisfiableConstructor dependency;
360     }
361 
362     /**
363      * Instantiate class with field to inject whose type cannot be instantiated.
364      *
365      * @param cut
366      *            the cut
367      */
368     @Test
369     void instantiateClassWithFieldToInjectWhoseTypeCannotBeInstantiated(
370             @Tested(fullyInitialized = true) ClassWithFieldToInject cut) {
371         assertNotNull(cut);
372         assertNull(cut.dependency);
373     }
374 
375     /**
376      * The Interface InterfaceDependency.
377      */
378     interface InterfaceDependency {
379     }
380 
381     /**
382      * The Class ClassWithInterfaceInConstructor.
383      */
384     static class ClassWithInterfaceInConstructor {
385         /**
386          * Instantiates a new class with interface in constructor.
387          *
388          * @param someValue
389          *            the some value
390          */
391         ClassWithInterfaceInConstructor(@SuppressWarnings("unused") InterfaceDependency someValue) {
392         }
393     }
394 
395     /**
396      * Instantiate class with interface in constructor.
397      *
398      * @param cut
399      *            the cut
400      */
401     @Test
402     void instantiateClassWithInterfaceInConstructor(
403             @Tested(fullyInitialized = true) ClassWithInterfaceInConstructor cut) {
404         assertNotNull(cut);
405     }
406 
407 }