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.assertFalse;
10  import static org.junit.jupiter.api.Assertions.assertNotNull;
11  import static org.junit.jupiter.api.Assertions.assertNull;
12  import static org.junit.jupiter.api.Assertions.assertSame;
13  import static org.junit.jupiter.api.Assertions.assertTrue;
14  
15  import jakarta.annotation.Resource;
16  import jakarta.annotation.sql.DataSourceDefinition;
17  import jakarta.annotation.sql.DataSourceDefinitions;
18  import jakarta.ejb.EJB;
19  import jakarta.enterprise.context.Conversation;
20  import jakarta.inject.Inject;
21  
22  import java.io.PrintWriter;
23  import java.sql.Connection;
24  import java.util.logging.Logger;
25  
26  import javax.sql.ConnectionPoolDataSource;
27  import javax.sql.DataSource;
28  import javax.sql.PooledConnection;
29  import javax.sql.XAConnection;
30  import javax.sql.XADataSource;
31  
32  import mockit.integration.junit5.JMockitExtension;
33  
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.api.extension.ExtendWith;
36  import org.springframework.beans.factory.annotation.Autowired;
37  
38  /**
39   * The Class TestedClassWithFullAnnotatedDITest.
40   */
41  @ExtendWith(JMockitExtension.class)
42  @SuppressWarnings("ParameterHidesMemberVariable")
43  class TestedClassWithFullAnnotatedDITest {
44  
45      /**
46       * The Class DummyDataSource.
47       */
48      public static class DummyDataSource implements DataSource {
49  
50          /** The url. */
51          private String url;
52  
53          /** The user. */
54          private String user;
55  
56          /** The password. */
57          String password;
58  
59          /**
60           * Gets the url.
61           *
62           * @return the url
63           */
64          public String getUrl() {
65              return url;
66          }
67  
68          /**
69           * Sets the url.
70           *
71           * @param url
72           *            the new url
73           */
74          @SuppressWarnings("unused")
75          public void setUrl(String url) {
76              this.url = url;
77          }
78  
79          /**
80           * Gets the user.
81           *
82           * @return the user
83           */
84          public String getUser() {
85              return user;
86          }
87  
88          /**
89           * Sets the user.
90           *
91           * @param user
92           *            the new user
93           */
94          @SuppressWarnings("unused")
95          public void setUser(String user) {
96              this.user = user;
97          }
98  
99          /**
100          * Sets the password.
101          *
102          * @param password
103          *            the new password
104          */
105         @SuppressWarnings("unused")
106         public void setPassword(String password) {
107             this.password = password;
108         }
109 
110         @Override
111         public Connection getConnection() {
112             return null;
113         }
114 
115         @Override
116         public Connection getConnection(String username, String password) {
117             return null;
118         }
119 
120         @Override
121         public <T> T unwrap(Class<T> iface) {
122             return null;
123         }
124 
125         @Override
126         public boolean isWrapperFor(Class<?> iface) {
127             return false;
128         }
129 
130         @Override
131         public PrintWriter getLogWriter() {
132             return null;
133         }
134 
135         @Override
136         public void setLogWriter(PrintWriter out) {
137         }
138 
139         @Override
140         public void setLoginTimeout(int seconds) {
141         }
142 
143         @Override
144         public int getLoginTimeout() {
145             return 0;
146         }
147 
148         @Override
149         public Logger getParentLogger() {
150             return null;
151         }
152     }
153 
154     /**
155      * The Class TestedClass.
156      */
157     @DataSourceDefinition(name = "java:global/jdbc/testDS", className = "mockit.TestedClassWithFullAnnotatedDITest$DummyDataSource", url = "jdbc:testDb:test", user = "tests", password = "test123")
158     static final class TestedClass {
159 
160         /** The action. */
161         @Inject
162         Runnable action;
163 
164         /** The dependency 1. */
165         @Autowired
166         ItfWithSingleImpl dependency1;
167 
168         /** The dependency 2. */
169         @Resource
170         ItfWithSingleImpl dependency2;
171 
172         /** The another dependency. */
173         @Inject
174         ItfWithTwoImpls anotherDependency;
175 
176         /** The log 1. */
177         @Inject
178         private Logger log1;
179 
180         /** The log 2. */
181         @Inject
182         private Logger log2;
183 
184         /** The collaborator. */
185         Collaborator collaborator;
186 
187         /** The conversation. */
188         @Inject
189         Conversation conversation;
190 
191         /** The ds. */
192         @Resource(lookup = "java:global/jdbc/testDS")
193         DataSource ds;
194     }
195 
196     /**
197      * The Class PooledDataSource.
198      */
199     public static final class PooledDataSource extends DummyDataSource implements ConnectionPoolDataSource {
200         @Override
201         public PooledConnection getPooledConnection() {
202             return null;
203         }
204 
205         @Override
206         public PooledConnection getPooledConnection(String user, String password) {
207             return null;
208         }
209     }
210 
211     /**
212      * The Class DistributedDataSource.
213      */
214     public static final class DistributedDataSource extends DummyDataSource implements XADataSource {
215         @Override
216         public XAConnection getXAConnection() {
217             return null;
218         }
219 
220         @Override
221         public XAConnection getXAConnection(String user, String password) {
222             return null;
223         }
224     }
225 
226     /**
227      * The Class AnotherTestedClass.
228      */
229     @DataSourceDefinitions({
230             @DataSourceDefinition(name = "regularDS", className = "mockit.TestedClassWithFullAnnotatedDITest$DummyDataSource", url = "jdbc:oracle:test", user = "tests", password = "test123"),
231             @DataSourceDefinition(name = "pooledDS", className = "mockit.TestedClassWithFullAnnotatedDITest$PooledDataSource", url = "jdbc:hsqldb:db", user = "pool", password = "test123"),
232             @DataSourceDefinition(name = "distributedDS", className = "mockit.TestedClassWithFullAnnotatedDITest$DistributedDataSource", url = "jdbc:postgresql:database", user = "xa", password = "test123") })
233     static class AnotherTestedClass {
234 
235         /** The ds 1. */
236         @Resource(lookup = "regularDS")
237         DataSource ds1;
238 
239         /** The ds 2. */
240         @Resource(lookup = "pooledDS")
241         ConnectionPoolDataSource ds2;
242 
243         /** The ds 3. */
244         @Resource(lookup = "distributedDS")
245         XADataSource ds3;
246 
247         /** The ds 4. */
248         @Resource(name = "regularDS")
249         DataSource ds4;
250     }
251 
252     /**
253      * The Class Collaborator.
254      */
255     static class Collaborator {
256     }
257 
258     /**
259      * The Interface ItfWithSingleImpl.
260      */
261     public interface ItfWithSingleImpl {
262     }
263 
264     /**
265      * The Class SingleImpl.
266      */
267     public static final class SingleImpl implements ItfWithSingleImpl {
268         /** The ejb. */
269         @EJB
270         ItfToBeMocked ejb;
271     }
272 
273     /**
274      * The Interface ItfWithTwoImpls.
275      */
276     public interface ItfWithTwoImpls {
277     }
278 
279     /**
280      * The Class Impl1.
281      */
282     @SuppressWarnings("unused")
283     public static final class Impl1 implements ItfWithTwoImpls {
284     }
285 
286     /**
287      * The Class Impl2.
288      */
289     public static final class Impl2 implements ItfWithTwoImpls {
290     }
291 
292     /**
293      * The Interface ItfToBeMocked.
294      */
295     public interface ItfToBeMocked {
296     }
297 
298     /** The dep 1. */
299     @Tested
300     SingleImpl dep1;
301 
302     /** The another dep. */
303     @Tested
304     Impl2 anotherDep;
305 
306     /** The collaborator. */
307     @Tested
308     Collaborator collaborator;
309 
310     /** The tested. */
311     @Tested(fullyInitialized = true)
312     TestedClass tested;
313 
314     /** The action. */
315     // Without these injectables, a "missing @Injectable" exception occurs for each unresolved field.
316     @Injectable
317     Runnable action;
318 
319     /** The ejb. */
320     @Injectable
321     ItfToBeMocked ejb;
322 
323     /**
324      * Inject initialized dependencies for interfaces having tested objects of implementation class types.
325      */
326     @Test
327     void injectInitializedDependenciesForInterfacesHavingTestedObjectsOfImplementationClassTypes() {
328         assertSame(action, tested.action);
329         assertNotNull(tested.dependency1);
330         assertSame(tested.dependency1, tested.dependency2);
331         assertTrue(tested.anotherDependency instanceof Impl2);
332         assertSame(ejb, ((SingleImpl) tested.dependency1).ejb);
333     }
334 
335     /**
336      * Inject logger fields with logger created with tested class name.
337      */
338     @Test
339     void injectLoggerFieldsWithLoggerCreatedWithTestedClassName() {
340         assertEquals(TestedClass.class.getName(), tested.log1.getName());
341         assertSame(tested.log2, tested.log1);
342     }
343 
344     /**
345      * Inject non annotated field from matching tested field.
346      */
347     @Test
348     void injectNonAnnotatedFieldFromMatchingTestedField() {
349         assertSame(collaborator, tested.collaborator);
350     }
351 
352     /** The conversation. */
353     @Tested
354     Conversation conversation;
355 
356     /**
357      * Manage conversation context.
358      */
359     @Test
360     void manageConversationContext() {
361         assertNotNull(conversation);
362         assertSame(tested.conversation, conversation);
363         assertTrue(conversation.isTransient());
364 
365         assertEquals(0, conversation.getTimeout());
366         conversation.setTimeout(1500);
367         assertEquals(1500, conversation.getTimeout());
368 
369         assertNull(conversation.getId());
370 
371         conversation.begin();
372         assertFalse(conversation.isTransient());
373         assertNotNull(conversation.getId());
374 
375         conversation.end();
376         assertTrue(conversation.isTransient());
377         assertNull(conversation.getId());
378 
379         conversation.begin("test");
380         assertFalse(conversation.isTransient());
381         assertEquals("test", conversation.getId());
382     }
383 
384     /**
385      * Inject data source configured from single data source definition.
386      */
387     @Test
388     void injectDataSourceConfiguredFromSingleDataSourceDefinition() {
389         assertTrue(tested.ds instanceof DummyDataSource);
390 
391         DummyDataSource ds = (DummyDataSource) tested.ds;
392         assertEquals("jdbc:testDb:test", ds.getUrl());
393         assertEquals("tests", ds.getUser());
394         assertEquals("test123", ds.password);
395     }
396 
397     /** The tested 2. */
398     @Tested(fullyInitialized = true)
399     AnotherTestedClass tested2;
400 
401     /**
402      * Inject multiple data sources configured from different data source definitions.
403      */
404     @Test
405     void injectMultipleDataSourcesConfiguredFromDifferentDataSourceDefinitions() {
406         assertTrue(tested2.ds1 instanceof DummyDataSource);
407         assertTrue(tested2.ds2 instanceof PooledDataSource);
408         assertTrue(tested2.ds3 instanceof DistributedDataSource);
409         assertSame(tested2.ds1, tested2.ds4);
410     }
411 }