View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertFalse;
5   import static org.junit.jupiter.api.Assertions.assertNotNull;
6   import static org.junit.jupiter.api.Assertions.assertNotSame;
7   import static org.junit.jupiter.api.Assertions.assertNull;
8   import static org.junit.jupiter.api.Assertions.assertSame;
9   import static org.junit.jupiter.api.Assertions.assertTrue;
10  import static org.junit.jupiter.api.Assertions.fail;
11  
12  import java.io.File;
13  import java.io.IOException;
14  import java.io.Writer;
15  import java.net.URI;
16  import java.net.URISyntaxException;
17  import java.nio.charset.StandardCharsets;
18  import java.nio.file.Files;
19  import java.nio.file.Path;
20  import java.util.List;
21  import java.util.Map;
22  
23  import javax.annotation.PostConstruct;
24  import javax.annotation.PreDestroy;
25  import javax.annotation.Resource;
26  import javax.ejb.EJB;
27  import javax.inject.Inject;
28  import javax.persistence.Cache;
29  import javax.persistence.EntityGraph;
30  import javax.persistence.EntityManager;
31  import javax.persistence.EntityManagerFactory;
32  import javax.persistence.EntityTransaction;
33  import javax.persistence.FlushModeType;
34  import javax.persistence.LockModeType;
35  import javax.persistence.Persistence;
36  import javax.persistence.PersistenceContext;
37  import javax.persistence.PersistenceUnit;
38  import javax.persistence.PersistenceUnitUtil;
39  import javax.persistence.Query;
40  import javax.persistence.StoredProcedureQuery;
41  import javax.persistence.SynchronizationType;
42  import javax.persistence.TypedQuery;
43  import javax.persistence.criteria.CriteriaBuilder;
44  import javax.persistence.criteria.CriteriaDelete;
45  import javax.persistence.criteria.CriteriaQuery;
46  import javax.persistence.criteria.CriteriaUpdate;
47  import javax.persistence.metamodel.Metamodel;
48  import javax.servlet.ServletContext;
49  import javax.servlet.http.HttpSession;
50  
51  import org.junit.jupiter.api.AfterAll;
52  import org.junit.jupiter.api.AfterEach;
53  import org.junit.jupiter.api.BeforeAll;
54  import org.junit.jupiter.api.MethodOrderer.MethodName;
55  import org.junit.jupiter.api.Test;
56  import org.junit.jupiter.api.TestMethodOrder;
57  
58  /**
59   * The Class TestedClassWithFullStandardDITest.
60   */
61  @TestMethodOrder(MethodName.class)
62  final class TestedClassWithFullStandardDITest {
63  
64      /**
65       * The Class TestedClass.
66       */
67      public static class TestedClass {
68  
69          /** The dependency to be mocked. */
70          @Inject
71          private Runnable dependencyToBeMocked;
72  
73          /** The dependency 2. */
74          @Inject
75          private FirstLevelDependency dependency2;
76  
77          /** The dependency 3. */
78          @Resource
79          private FirstLevelDependency dependency3;
80  
81          /** The common dependency. */
82          @Inject
83          private CommonDependency commonDependency;
84  
85          /** The text. */
86          String text;
87  
88          /** The initialized. */
89          boolean initialized;
90  
91          /** The destroyed. */
92          static boolean destroyed;
93  
94          /**
95           * Initialize.
96           */
97          @PostConstruct
98          void initialize() {
99              assertNotNull(dependency3);
100             initialized = true;
101         }
102 
103         /**
104          * Destroy.
105          */
106         @PreDestroy
107         void destroy() {
108             assertTrue(initialized, "TestedClass not initialized");
109             destroyed = true;
110         }
111     }
112 
113     /**
114      * The Class AnotherTestedClass.
115      */
116     static final class AnotherTestedClass {
117 
118         /** The em. */
119         @PersistenceContext
120         EntityManager em;
121 
122         /** The session. */
123         @Inject
124         HttpSession session;
125 
126         /** The application context. */
127         @Inject
128         ServletContext applicationContext;
129     }
130 
131     /**
132      * The Class FirstLevelDependency.
133      */
134     public static class FirstLevelDependency {
135 
136         /** The dependency. */
137         @EJB
138         private SecondLevelDependency dependency;
139 
140         /** The static dependency. */
141         @Inject
142         private static SecondLevelDependency staticDependency;
143 
144         /** The common dependency. */
145         @Inject
146         private CommonDependency commonDependency;
147 
148         /** The dependency to be mocked. */
149         @Resource
150         private static Runnable dependencyToBeMocked;
151 
152         /** The em. */
153         @PersistenceContext
154         private EntityManager em;
155     }
156 
157     /**
158      * The Class SecondLevelDependency.
159      */
160     public static class SecondLevelDependency {
161 
162         /** The common dependency. */
163         @Inject
164         CommonDependency commonDependency;
165 
166         /** The em. */
167         @PersistenceContext
168         private EntityManager em;
169 
170         /** The servlet context. */
171         @Inject
172         ServletContext servletContext;
173 
174         /** The http session. */
175         @Inject
176         HttpSession httpSession;
177 
178         /** The initialized. */
179         boolean initialized;
180 
181         /** The terminated. */
182         static boolean terminated;
183 
184         /**
185          * Initialize.
186          */
187         @PostConstruct
188         void initialize() {
189             initialized = true;
190         }
191 
192         /**
193          * Terminate.
194          */
195         @PreDestroy
196         void terminate() {
197             terminated = true;
198         }
199     }
200 
201     /**
202      * The Class CommonDependency.
203      */
204     public static class CommonDependency {
205 
206         /** The em factory. */
207         @PersistenceUnit(unitName = "test")
208         private EntityManagerFactory emFactory;
209 
210         /** The em. */
211         @PersistenceContext(unitName = "test")
212         private EntityManager em;
213     }
214 
215     /** The tested. */
216     @Tested(fullyInitialized = true)
217     TestedClass tested;
218 
219     /** The tested 2. */
220     @Tested(fullyInitialized = true)
221     AnotherTestedClass tested2;
222 
223     /** The mocked dependency. */
224     @Injectable
225     Runnable mockedDependency;
226 
227     /** The persistence xml file. */
228     static File persistenceXmlFile;
229 
230     /** The named EM factory. */
231     static EntityManagerFactory namedEMFactory;
232 
233     /** The named EM. */
234     static EntityManager namedEM;
235 
236     /** The default EM factory. */
237     static EntityManagerFactory defaultEMFactory;
238 
239     /** The default EM. */
240     static EntityManager defaultEM;
241 
242     /**
243      * Sets the up persistence.
244      *
245      * @throws Exception
246      *             the exception
247      */
248     @BeforeAll
249     @SuppressWarnings("rawtypes")
250     static void setUpPersistence() throws Exception {
251         final class FakeEntityManager implements EntityManager {
252             @Override
253             public void persist(Object entity) {
254             }
255 
256             @Override
257             public <T> T merge(T entity) {
258                 return null;
259             }
260 
261             @Override
262             public void remove(Object entity) {
263             }
264 
265             @Override
266             public <T> T find(Class<T> entityClass, Object primaryKey) {
267                 return null;
268             }
269 
270             @Override
271             public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
272                 return null;
273             }
274 
275             @Override
276             public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode) {
277                 return null;
278             }
279 
280             @Override
281             public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode,
282                     Map<String, Object> properties) {
283                 return null;
284             }
285 
286             @Override
287             public <T> T getReference(Class<T> entityClass, Object primaryKey) {
288                 return null;
289             }
290 
291             @Override
292             public void flush() {
293             }
294 
295             @Override
296             public void setFlushMode(FlushModeType flushMode) {
297             }
298 
299             @Override
300             public FlushModeType getFlushMode() {
301                 return null;
302             }
303 
304             @Override
305             public void lock(Object entity, LockModeType lockMode) {
306             }
307 
308             @Override
309             public void lock(Object entity, LockModeType lockMode, Map<String, Object> properties) {
310             }
311 
312             @Override
313             public void refresh(Object entity) {
314             }
315 
316             @Override
317             public void refresh(Object entity, Map<String, Object> properties) {
318             }
319 
320             @Override
321             public void refresh(Object entity, LockModeType lockMode) {
322             }
323 
324             @Override
325             public void refresh(Object entity, LockModeType lockMode, Map<String, Object> properties) {
326             }
327 
328             @Override
329             public void clear() {
330             }
331 
332             @Override
333             public void detach(Object entity) {
334             }
335 
336             @Override
337             public boolean contains(Object entity) {
338                 return false;
339             }
340 
341             @Override
342             public LockModeType getLockMode(Object entity) {
343                 return null;
344             }
345 
346             @Override
347             public void setProperty(String propertyName, Object value) {
348             }
349 
350             @Override
351             public Map<String, Object> getProperties() {
352                 return null;
353             }
354 
355             @Override
356             public Query createQuery(String qlString) {
357                 return null;
358             }
359 
360             @Override
361             public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
362                 return null;
363             }
364 
365             @Override
366             public Query createQuery(CriteriaUpdate updateQuery) {
367                 return null;
368             }
369 
370             @Override
371             public Query createQuery(CriteriaDelete deleteQuery) {
372                 return null;
373             }
374 
375             @Override
376             public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) {
377                 return null;
378             }
379 
380             @Override
381             public Query createNamedQuery(String name) {
382                 return null;
383             }
384 
385             @Override
386             public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
387                 return null;
388             }
389 
390             @Override
391             public Query createNativeQuery(String sqlString) {
392                 return null;
393             }
394 
395             @Override
396             public Query createNativeQuery(String sqlString, Class resultClass) {
397                 return null;
398             }
399 
400             @Override
401             public Query createNativeQuery(String sqlString, String resultSetMapping) {
402                 return null;
403             }
404 
405             @Override
406             public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
407                 return null;
408             }
409 
410             @Override
411             public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
412                 return null;
413             }
414 
415             @Override
416             public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
417                 return null;
418             }
419 
420             @Override
421             public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
422                 return null;
423             }
424 
425             @Override
426             public void joinTransaction() {
427             }
428 
429             @Override
430             public boolean isJoinedToTransaction() {
431                 return false;
432             }
433 
434             @Override
435             public <T> T unwrap(Class<T> cls) {
436                 return null;
437             }
438 
439             @Override
440             public Object getDelegate() {
441                 return null;
442             }
443 
444             @Override
445             public void close() {
446             }
447 
448             @Override
449             public boolean isOpen() {
450                 return false;
451             }
452 
453             @Override
454             public EntityTransaction getTransaction() {
455                 return null;
456             }
457 
458             @Override
459             public EntityManagerFactory getEntityManagerFactory() {
460                 return null;
461             }
462 
463             @Override
464             public CriteriaBuilder getCriteriaBuilder() {
465                 return null;
466             }
467 
468             @Override
469             public Metamodel getMetamodel() {
470                 return null;
471             }
472 
473             @Override
474             public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) {
475                 return null;
476             }
477 
478             @Override
479             public EntityGraph<?> createEntityGraph(String graphName) {
480                 return null;
481             }
482 
483             @Override
484             public EntityGraph<?> getEntityGraph(String graphName) {
485                 return null;
486             }
487 
488             @Override
489             public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
490                 return null;
491             }
492         }
493         namedEM = new FakeEntityManager();
494         defaultEM = new FakeEntityManager();
495 
496         final class FakeEntityManagerFactory implements EntityManagerFactory {
497             final EntityManager em;
498 
499             FakeEntityManagerFactory(EntityManager em) {
500                 this.em = em;
501             }
502 
503             @Override
504             public EntityManager createEntityManager() {
505                 return em;
506             }
507 
508             @Override
509             public EntityManager createEntityManager(Map map) {
510                 return null;
511             }
512 
513             @Override
514             public EntityManager createEntityManager(SynchronizationType synchronizationType) {
515                 return null;
516             }
517 
518             @Override
519             public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
520                 return null;
521             }
522 
523             @Override
524             public CriteriaBuilder getCriteriaBuilder() {
525                 return null;
526             }
527 
528             @Override
529             public Metamodel getMetamodel() {
530                 return null;
531             }
532 
533             @Override
534             public boolean isOpen() {
535                 return false;
536             }
537 
538             @Override
539             public void close() {
540             }
541 
542             @Override
543             public Map<String, Object> getProperties() {
544                 return null;
545             }
546 
547             @Override
548             public Cache getCache() {
549                 return null;
550             }
551 
552             @Override
553             public PersistenceUnitUtil getPersistenceUnitUtil() {
554                 return null;
555             }
556 
557             @Override
558             public void addNamedQuery(String name, Query query) {
559             }
560 
561             @Override
562             public <T> T unwrap(Class<T> cls) {
563                 return null;
564             }
565 
566             @Override
567             public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
568             }
569         }
570         namedEMFactory = new FakeEntityManagerFactory(namedEM);
571         defaultEMFactory = new FakeEntityManagerFactory(defaultEM);
572 
573         new MockUp<Persistence>() {
574             @Mock
575             EntityManagerFactory createEntityManagerFactory(String persistenceUnitName) {
576                 if ("test".equals(persistenceUnitName)) {
577                     return namedEMFactory;
578                 }
579 
580                 if ("default".equals(persistenceUnitName)) {
581                     return defaultEMFactory;
582                 }
583 
584                 fail("Unexpected persistence unit");
585                 return null;
586             }
587         };
588 
589         createTemporaryPersistenceXmlFileWithDefaultPersistenceUnit();
590     }
591 
592     /**
593      * Creates the temporary persistence xml file with default persistence unit.
594      *
595      * @throws IOException
596      *             Signals that an I/O exception has occurred.
597      * @throws URISyntaxException
598      *             the URI syntax exception
599      */
600     static void createTemporaryPersistenceXmlFileWithDefaultPersistenceUnit() throws IOException, URISyntaxException {
601         URI rootOfClasspath = TestedClass.class.getProtectionDomain().getCodeSource().getLocation().toURI();
602         File tempFolder = Path.of(rootOfClasspath).resolve("META-INF").toFile();
603         if (tempFolder.mkdir()) {
604             tempFolder.deleteOnExit();
605         }
606 
607         persistenceXmlFile = tempFolder.toPath().resolve("persistence.xml").toFile();
608 
609         Writer xmlWriter = Files.newBufferedWriter(persistenceXmlFile.toPath(), StandardCharsets.UTF_8);
610         xmlWriter.write("<persistence><persistence-unit name='default'/></persistence>");
611         xmlWriter.close();
612     }
613 
614     /**
615      * Delete default persistence xml file.
616      */
617     @AfterAll
618     static void deleteDefaultPersistenceXmlFile() {
619         persistenceXmlFile.delete();
620         persistenceXmlFile.getParentFile().delete();
621     }
622 
623     /**
624      * Use fully initialized tested object.
625      */
626     @Test
627     void useFullyInitializedTestedObject() {
628         // First level dependencies:
629         assertSame(mockedDependency, tested.dependencyToBeMocked);
630         assertNotNull(tested.dependency2);
631         assertSame(tested.dependency2, tested.dependency3);
632         assertNotNull(tested.commonDependency);
633         assertNull(tested.text);
634 
635         // Second level dependencies:
636         assertNotNull(tested.dependency2.dependency);
637         assertSame(FirstLevelDependency.staticDependency, tested.dependency2.dependency);
638         assertSame(tested.dependency3.dependency, tested.dependency2.dependency);
639         assertSame(tested.commonDependency, tested.dependency2.commonDependency);
640         assertSame(tested.commonDependency, tested.dependency3.commonDependency);
641         assertSame(mockedDependency, FirstLevelDependency.dependencyToBeMocked);
642         assertSame(mockedDependency, FirstLevelDependency.dependencyToBeMocked);
643         assertSame(defaultEM, tested.dependency2.em);
644         assertSame(tested.dependency2.em, tested.dependency3.em);
645         assertSame(namedEMFactory, tested.commonDependency.emFactory);
646         assertSame(namedEM, tested.commonDependency.em);
647         assertNotSame(tested.dependency2.em, tested.commonDependency.em);
648         assertSame(tested2.em, tested.dependency2.em);
649 
650         // Third level dependencies:
651         assertSame(tested.commonDependency, tested.dependency2.dependency.commonDependency);
652         assertSame(tested.dependency2.em, tested.dependency2.dependency.em);
653 
654         // Lifecycle methods:
655         assertTrue(tested.initialized);
656         assertTrue(tested.dependency2.dependency.initialized);
657     }
658 
659     /**
660      * Use fully initialized tested object again.
661      */
662     @Test
663     void useFullyInitializedTestedObjectAgain() {
664         assertNull(tested.text);
665     }
666 
667     /**
668      * Verify emulated http session.
669      */
670     @Test
671     void verifyEmulatedHttpSession() {
672         HttpSession session = tested2.session;
673         assertFalse(session.isNew());
674         assertFalse(session.getId().isEmpty());
675         assertTrue(session.getCreationTime() > 0);
676         assertTrue(session.getLastAccessedTime() > 0);
677         assertFalse(session.getAttributeNames().hasMoreElements());
678 
679         session.setMaxInactiveInterval(600);
680         assertEquals(600, session.getMaxInactiveInterval());
681 
682         session.setAttribute("test", 123);
683         assertEquals(123, session.getAttribute("test"));
684         assertEquals("test", session.getAttributeNames().nextElement());
685 
686         session.removeAttribute("test");
687         assertNull(session.getAttribute("test"));
688 
689         session.setAttribute("test2", "abc");
690         session.invalidate();
691 
692         try {
693             session.isNew();
694             fail();
695         } catch (IllegalStateException invalidatedSession) {
696             /* ok */ }
697         try {
698             session.getCreationTime();
699             fail();
700         } catch (IllegalStateException invalidatedSession) {
701             /* ok */ }
702         try {
703             session.getLastAccessedTime();
704             fail();
705         } catch (IllegalStateException invalidatedSession) {
706             /* ok */ }
707         try {
708             session.getAttributeNames();
709             fail();
710         } catch (IllegalStateException invalidatedSession) {
711             /* ok */ }
712         try {
713             session.getAttribute("test2");
714             fail();
715         } catch (IllegalStateException invalidatedSession) {
716             /* ok */ }
717         try {
718             session.setAttribute("x", "");
719             fail();
720         } catch (IllegalStateException invalidatedSession) {
721             /* ok */ }
722         try {
723             session.removeAttribute("x");
724             fail();
725         } catch (IllegalStateException invalidatedSession) {
726             /* ok */ }
727         try {
728             session.invalidate();
729             fail();
730         } catch (IllegalStateException invalidatedSession) {
731             /* ok */ }
732 
733         assertSame(tested2.applicationContext, session.getServletContext());
734         assertSame(session, tested.dependency3.dependency.httpSession);
735     }
736 
737     /**
738      * Verify emulated servlet context.
739      */
740     @Test
741     void verifyEmulatedServletContext() {
742         ServletContext ctx = tested2.applicationContext;
743 
744         assertFalse(ctx.getAttributeNames().hasMoreElements());
745 
746         ctx.setInitParameter("test", "abc");
747         assertEquals("abc", ctx.getInitParameter("test"));
748         assertEquals("test", ctx.getInitParameterNames().nextElement());
749 
750         ctx.setAttribute("test", 123);
751         assertEquals(123, ctx.getAttribute("test"));
752         assertEquals("test", ctx.getAttributeNames().nextElement());
753 
754         ctx.removeAttribute("test");
755         assertNull(ctx.getAttribute("test"));
756 
757         assertSame(ctx, tested.dependency2.dependency.servletContext);
758     }
759 
760     /**
761      * Verify that tested fields were cleared and pre destroy methods were executed.
762      */
763     @AfterEach
764     void verifyThatTestedFieldsWereClearedAndPreDestroyMethodsWereExecuted() {
765         assertNull(tested);
766         assertNull(tested2);
767         assertTrue(TestedClass.destroyed);
768         assertTrue(SecondLevelDependency.terminated);
769     }
770 
771     /**
772      * Clear entity managers.
773      */
774     @AfterEach
775     void clearEntityManagers() {
776         namedEM = null;
777         defaultEM = null;
778     }
779 }