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