1
2
3
4
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.assertNotSame;
12 import static org.junit.jupiter.api.Assertions.assertNull;
13 import static org.junit.jupiter.api.Assertions.assertSame;
14 import static org.junit.jupiter.api.Assertions.assertTrue;
15
16 import java.io.Serializable;
17 import java.util.Date;
18 import java.util.List;
19
20 import mockit.integration.junit5.JMockitExtension;
21
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.MethodOrderer.MethodName;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.TestMethodOrder;
26 import org.junit.jupiter.api.extension.ExtendWith;
27
28
29
30
31 @ExtendWith(JMockitExtension.class)
32 @TestMethodOrder(MethodName.class)
33 class CascadingFieldTest {
34
35
36
37
38 static class Foo {
39
40
41
42
43
44
45 Bar getBar() {
46 return null;
47 }
48
49
50
51
52
53
54 static Bar globalBar() {
55 return null;
56 }
57
58
59
60
61
62
63
64 void doSomething(String s) {
65 throw new RuntimeException(s);
66 }
67
68
69
70
71
72
73 int getIntValue() {
74 return 1;
75 }
76
77
78
79
80
81
82 Boolean getBooleanValue() {
83 return true;
84 }
85
86
87
88
89
90
91 String getStringValue() {
92 return "abc";
93 }
94
95
96
97
98
99
100 public final Date getDate() {
101 return null;
102 }
103
104
105
106
107
108
109 final List<Integer> getList() {
110 return null;
111 }
112 }
113
114
115
116
117 static class Bar {
118
119
120
121
122 Bar() {
123 throw new RuntimeException();
124 }
125
126
127
128
129
130
131 int doSomething() {
132 return 1;
133 }
134
135
136
137
138
139
140 boolean isDone() {
141 return false;
142 }
143
144
145
146
147
148
149 Short getShort() {
150 return 1;
151 }
152
153
154
155
156
157
158 List<?> getList() {
159 return null;
160 }
161
162
163
164
165
166
167 Baz getBaz() {
168 return null;
169 }
170
171
172
173
174
175
176 Runnable getTask() {
177 return null;
178 }
179 }
180
181
182
183
184 static final class Baz {
185
186
187 final E e;
188
189
190
191
192
193
194
195 Baz(E e) {
196 this.e = e;
197 }
198
199
200
201
202
203
204 E getE() {
205 return e;
206 }
207
208
209
210
211 void doSomething() {
212 }
213 }
214
215
216
217
218 public enum E {
219
220 A,
221
222 B
223 }
224
225
226
227
228 public interface A {
229
230
231
232
233
234 B getB();
235 }
236
237
238
239
240 public interface B {
241
242
243
244
245
246 C getC();
247 }
248
249
250
251
252 public interface C {
253 }
254
255
256 @Mocked
257 Foo foo;
258
259
260 @Mocked
261 A a;
262
263
264
265
266 @BeforeEach
267 void recordCommonExpectations() {
268 new Expectations() {
269 {
270 Bar bar = foo.getBar();
271 minTimes = 0;
272 bar.isDone();
273 result = true;
274 minTimes = 0;
275 }
276 };
277 }
278
279
280
281
282 @Test
283 void obtainCascadedInstancesAtAllLevels() {
284 assertNotNull(foo.getBar());
285 assertNotNull(foo.getBar().getList());
286 assertNotNull(foo.getBar().getBaz());
287 assertNotNull(foo.getBar().getTask());
288
289 B b = a.getB();
290 assertNotNull(b);
291 assertNotNull(b.getC());
292 }
293
294
295
296
297 @Test
298 void obtainCascadedInstancesAtAllLevelsAgain() {
299 Bar bar = foo.getBar();
300 assertNotNull(bar);
301 assertNotNull(bar.getList());
302 assertNotNull(bar.getBaz());
303 assertNotNull(bar.getTask());
304
305 assertNotNull(a.getB());
306 assertNotNull(a.getB().getC());
307 }
308
309
310
311
312 @Test
313 void cascadeOneLevel() {
314 assertTrue(foo.getBar().isDone());
315 assertEquals(0, foo.getBar().doSomething());
316 assertEquals(0, Foo.globalBar().doSomething());
317 assertNotSame(foo.getBar(), Foo.globalBar());
318 assertEquals(0, foo.getBar().getShort().intValue());
319
320 foo.doSomething("test");
321 assertEquals(0, foo.getIntValue());
322 assertFalse(foo.getBooleanValue());
323 assertNull(foo.getStringValue());
324 assertNotNull(foo.getDate());
325 assertTrue(foo.getList().isEmpty());
326
327 new Verifications() {
328 {
329 foo.doSomething(anyString);
330 }
331 };
332 }
333
334
335
336
337 @Test
338 void exerciseCascadingMockAgain() {
339 assertTrue(foo.getBar().isDone());
340 }
341
342
343
344
345
346
347
348
349
350 @Test
351 void recordUnambiguousExpectationsProducingDifferentCascadedInstances(@Mocked final Foo foo1,
352 @Mocked final Foo foo2) {
353 new Expectations() {
354 {
355 Date c1 = foo1.getDate();
356 Date c2 = foo2.getDate();
357 assertNotSame(c1, c2);
358 }
359 };
360
361 Date d1 = foo1.getDate();
362 Date d2 = foo2.getDate();
363 assertNotSame(d1, d2);
364 }
365
366
367
368
369 @Test
370 void recordAmbiguousExpectationsOnInstanceMethodProducingTheSameCascadedInstance() {
371 new Expectations() {
372 {
373 Bar c1 = foo.getBar();
374 Bar c2 = foo.getBar();
375 assertSame(c1, c2);
376 }
377 };
378
379 Bar b1 = foo.getBar();
380 Bar b2 = foo.getBar();
381 assertSame(b1, b2);
382 }
383
384
385
386
387 @Test
388 void recordAmbiguousExpectationsOnStaticMethodProducingTheSameCascadedInstance() {
389 new Expectations() {
390 {
391 Bar c1 = Foo.globalBar();
392 Bar c2 = Foo.globalBar();
393 assertSame(c1, c2);
394 }
395 };
396
397 Bar b1 = Foo.globalBar();
398 Bar b2 = Foo.globalBar();
399 assertSame(b1, b2);
400 }
401
402
403
404
405
406
407
408
409
410
411 @Test
412 void recordAmbiguousExpectationWithMultipleCascadingCandidatesFollowedByExpectationRecordedOnFirstCandidate(
413 @Injectable final Bar bar1, @Injectable Bar bar2) {
414 new Expectations() {
415 {
416 foo.getBar();
417 bar1.doSomething();
418 }
419 };
420
421 foo.getBar();
422 bar1.doSomething();
423 }
424
425
426
427
428 static final class AnotherFoo {
429
430
431
432
433
434 Bar getBar() {
435 return null;
436 }
437 }
438
439
440 @Mocked
441 AnotherFoo anotherFoo;
442
443
444
445
446 @Test
447 void cascadingMockField() {
448 new Expectations() {
449 {
450 anotherFoo.getBar().doSomething();
451 result = 123;
452 }
453 };
454
455 assertEquals(123, new AnotherFoo().getBar().doSomething());
456 }
457
458
459
460
461 @Test
462 void cascadingInstanceAccessedFromDelegateMethod() {
463 new Expectations() {
464 {
465 foo.getIntValue();
466 result = new Delegate<Object>() {
467 @Mock
468 int delegate() {
469 return foo.getBar().doSomething();
470 }
471 };
472 }
473 };
474
475 assertEquals(0, foo.getIntValue());
476 }
477
478
479 @Mocked
480 BazCreatorAndConsumer bazCreatorAndConsumer;
481
482
483
484
485 static class BazCreatorAndConsumer {
486
487
488
489
490
491
492 Baz create() {
493 return null;
494 }
495
496
497
498
499
500
501
502 void consume(Baz arg) {
503 arg.toString();
504 }
505 }
506
507
508
509
510 @Test
511 void callMethodOnNonCascadedInstanceFromCustomArgumentMatcherWithCascadedInstanceAlsoCreated() {
512 Baz nonCascadedInstance = new Baz(E.A);
513 Baz cascadedInstance = bazCreatorAndConsumer.create();
514 assertNotSame(nonCascadedInstance, cascadedInstance);
515
516 bazCreatorAndConsumer.consume(nonCascadedInstance);
517
518 new Verifications() {
519 {
520 bazCreatorAndConsumer.consume(with(new Delegate<Baz>() {
521 @SuppressWarnings("unused")
522 boolean matches(Baz actual) {
523 return actual.getE() == E.A;
524 }
525 }));
526 }
527 };
528 }
529
530
531
532
533
534
535
536
537
538 static class GenericBaseClass1<T> {
539
540
541
542
543
544 T getValue() {
545 return null;
546 }
547 }
548
549
550
551
552
553
554
555 @Test
556 void cascadeGenericMethodFromSpecializedGenericClass(@Mocked GenericBaseClass1<C> mock) {
557 C value = mock.getValue();
558 assertNotNull(value);
559 }
560
561
562
563
564 static class ConcreteSubclass1 extends GenericBaseClass1<A> {
565 }
566
567
568
569
570
571
572
573 @Test
574 void cascadeGenericMethodOfConcreteSubclassWhichExtendsGenericClass(@Mocked final ConcreteSubclass1 mock) {
575 new Expectations() {
576 {
577 mock.getValue().getB().getC();
578 result = new C() {
579 };
580 }
581 };
582
583 A value = mock.getValue();
584 assertNotNull(value);
585 B b = value.getB();
586 assertNotNull(b);
587 assertNotNull(b.getC());
588
589 new FullVerifications() {
590 {
591 mock.getValue().getB().getC();
592 }
593 };
594 }
595
596
597
598
599 interface Ab extends A {
600 }
601
602
603
604
605
606
607
608 static class GenericBaseClass2<T extends A> {
609
610
611
612
613
614 T getValue() {
615 return null;
616 }
617 }
618
619
620
621
622 static class ConcreteSubclass2 extends GenericBaseClass2<Ab> {
623 }
624
625
626
627
628
629
630
631 @Test
632 void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundUsingInterface(
633 @Mocked final ConcreteSubclass2 mock) {
634 Ab value = mock.getValue();
635 assertNotNull(value);
636 value.getB().getC();
637
638 new Verifications() {
639 {
640 mock.getValue().getB().getC();
641 times = 1;
642 }
643 };
644 }
645
646
647
648
649
650
651
652 @Test
653 void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundOnlyInVerificationBlock(
654 @Mocked final ConcreteSubclass2 mock) {
655 new FullVerifications() {
656 {
657 Ab value = mock.getValue();
658 times = 0;
659 B b = value.getB();
660 times = 0;
661 b.getC();
662 times = 0;
663 }
664 };
665 }
666
667
668
669
670 static final class Action implements A {
671 @Override
672 public B getB() {
673 return null;
674 }
675 }
676
677
678
679
680 static final class ActionHolder extends GenericBaseClass2<Action> {
681 }
682
683
684
685
686
687
688
689 @Test
690 void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundUsingClass(
691 @Mocked final ActionHolder mock) {
692 new Expectations() {
693 {
694 mock.getValue().getB().getC();
695 }
696 };
697
698 mock.getValue().getB().getC();
699 }
700
701
702
703
704
705
706
707 static class Base<T extends Serializable> {
708
709
710
711
712
713 @SuppressWarnings("unchecked")
714 T value() {
715 return (T) Long.valueOf(123);
716 }
717 }
718
719
720
721
722 static class Derived1 extends Base<Long> {
723 }
724
725
726
727
728 static class Derived2 extends Base<Long> {
729 }
730
731
732
733
734 interface Factory1 {
735
736
737
738
739
740 Derived1 get1();
741 }
742
743
744
745
746 interface Factory2 {
747
748
749
750
751
752 Derived2 get2();
753 }
754
755
756 @Mocked
757 Factory1 factory1;
758
759
760 @Mocked
761 Factory2 factory2;
762
763
764
765
766 @Test
767 void useSubclassMockedThroughCascading() {
768 Derived1 d1 = factory1.get1();
769 Long v1 = d1.value();
770 assertNull(v1);
771
772 Long v2 = new Derived1().value();
773 assertEquals(123, v2.longValue());
774 }
775
776
777
778
779
780
781
782 @Test
783 void useSubclassPreviouslyMockedThroughCascadingWhileMockingSiblingSubclass(@Injectable Derived2 d2) {
784 Long v1 = new Derived1().value();
785 assertEquals(123, v1.longValue());
786
787 Long v2 = d2.value();
788 assertNull(v2);
789
790 Long v3 = new Derived2().value();
791 assertEquals(123, v3.longValue());
792 }
793 }