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
60
61 @TestMethodOrder(MethodName.class)
62 final class TestedClassWithFullStandardDITest {
63
64
65
66
67 public static class TestedClass {
68
69
70 @Inject
71 private Runnable dependencyToBeMocked;
72
73
74 @Inject
75 private FirstLevelDependency dependency2;
76
77
78 @Resource
79 private FirstLevelDependency dependency3;
80
81
82 @Inject
83 private CommonDependency commonDependency;
84
85
86 String text;
87
88
89 boolean initialized;
90
91
92 static boolean destroyed;
93
94
95
96
97 @PostConstruct
98 void initialize() {
99 assertNotNull(dependency3);
100 initialized = true;
101 }
102
103
104
105
106 @PreDestroy
107 void destroy() {
108 assertTrue(initialized, "TestedClass not initialized");
109 destroyed = true;
110 }
111 }
112
113
114
115
116 static final class AnotherTestedClass {
117
118
119 @PersistenceContext
120 EntityManager em;
121
122
123 @Inject
124 HttpSession session;
125
126
127 @Inject
128 ServletContext applicationContext;
129 }
130
131
132
133
134 public static class FirstLevelDependency {
135
136
137 @EJB
138 private SecondLevelDependency dependency;
139
140
141 @Inject
142 private static SecondLevelDependency staticDependency;
143
144
145 @Inject
146 private CommonDependency commonDependency;
147
148
149 @Resource
150 private static Runnable dependencyToBeMocked;
151
152
153 @PersistenceContext
154 private EntityManager em;
155 }
156
157
158
159
160 public static class SecondLevelDependency {
161
162
163 @Inject
164 CommonDependency commonDependency;
165
166
167 @PersistenceContext
168 private EntityManager em;
169
170
171 @Inject
172 ServletContext servletContext;
173
174
175 @Inject
176 HttpSession httpSession;
177
178
179 boolean initialized;
180
181
182 static boolean terminated;
183
184
185
186
187 @PostConstruct
188 void initialize() {
189 initialized = true;
190 }
191
192
193
194
195 @PreDestroy
196 void terminate() {
197 terminated = true;
198 }
199 }
200
201
202
203
204 public static class CommonDependency {
205
206
207 @PersistenceUnit(unitName = "test")
208 private EntityManagerFactory emFactory;
209
210
211 @PersistenceContext(unitName = "test")
212 private EntityManager em;
213 }
214
215
216 @Tested(fullyInitialized = true)
217 TestedClass tested;
218
219
220 @Tested(fullyInitialized = true)
221 AnotherTestedClass tested2;
222
223
224 @Injectable
225 Runnable mockedDependency;
226
227
228 static File persistenceXmlFile;
229
230
231 static EntityManagerFactory namedEMFactory;
232
233
234 static EntityManager namedEM;
235
236
237 static EntityManagerFactory defaultEMFactory;
238
239
240 static EntityManager defaultEM;
241
242
243
244
245
246
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
594
595
596
597
598
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
616
617 @AfterAll
618 static void deleteDefaultPersistenceXmlFile() {
619 persistenceXmlFile.delete();
620 persistenceXmlFile.getParentFile().delete();
621 }
622
623
624
625
626 @Test
627 void useFullyInitializedTestedObject() {
628
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
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
651 assertSame(tested.commonDependency, tested.dependency2.dependency.commonDependency);
652 assertSame(tested.dependency2.em, tested.dependency2.dependency.em);
653
654
655 assertTrue(tested.initialized);
656 assertTrue(tested.dependency2.dependency.initialized);
657 }
658
659
660
661
662 @Test
663 void useFullyInitializedTestedObjectAgain() {
664 assertNull(tested.text);
665 }
666
667
668
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 }
697 try {
698 session.getCreationTime();
699 fail();
700 } catch (IllegalStateException invalidatedSession) {
701 }
702 try {
703 session.getLastAccessedTime();
704 fail();
705 } catch (IllegalStateException invalidatedSession) {
706 }
707 try {
708 session.getAttributeNames();
709 fail();
710 } catch (IllegalStateException invalidatedSession) {
711 }
712 try {
713 session.getAttribute("test2");
714 fail();
715 } catch (IllegalStateException invalidatedSession) {
716 }
717 try {
718 session.setAttribute("x", "");
719 fail();
720 } catch (IllegalStateException invalidatedSession) {
721 }
722 try {
723 session.removeAttribute("x");
724 fail();
725 } catch (IllegalStateException invalidatedSession) {
726 }
727 try {
728 session.invalidate();
729 fail();
730 } catch (IllegalStateException invalidatedSession) {
731 }
732
733 assertSame(tested2.applicationContext, session.getServletContext());
734 assertSame(session, tested.dependency3.dependency.httpSession);
735 }
736
737
738
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
762
763 @AfterEach
764 void verifyThatTestedFieldsWereClearedAndPreDestroyMethodsWereExecuted() {
765 assertNull(tested);
766 assertNull(tested2);
767 assertTrue(TestedClass.destroyed);
768 assertTrue(SecondLevelDependency.terminated);
769 }
770
771
772
773
774 @AfterEach
775 void clearEntityManagers() {
776 namedEM = null;
777 defaultEM = null;
778 }
779 }