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.assertNull;
11 import static org.junit.jupiter.api.Assertions.assertTrue;
12 import static org.junit.jupiter.api.Assertions.fail;
13
14 import jakarta.xml.bind.annotation.XmlElement;
15
16 import java.lang.reflect.Constructor;
17 import java.util.Date;
18 import java.util.List;
19
20 import mockit.integration.junit5.ExpectedException;
21 import mockit.integration.junit5.JMockitExtension;
22 import mockit.internal.expectations.invocation.MissingInvocation;
23 import mockit.internal.expectations.invocation.UnexpectedInvocation;
24
25 import org.junit.jupiter.api.Assertions;
26 import org.junit.jupiter.api.Disabled;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
29
30
31
32
33 @ExtendWith(JMockitExtension.class)
34 @SuppressWarnings("deprecation")
35 class PartialMockingTest {
36
37
38
39
40 @Deprecated
41 static class Collaborator {
42
43
44 @Deprecated
45 protected int value;
46
47
48
49
50 Collaborator() {
51 value = -1;
52 }
53
54
55
56
57
58
59
60 @Deprecated
61 Collaborator(@Deprecated int value) {
62 this.value = value;
63 }
64
65
66
67
68
69
70 final int getValue() {
71 return value;
72 }
73
74
75
76
77
78
79
80 void setValue(int value) {
81 this.value = value;
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96 @SuppressWarnings("unused")
97 final boolean simpleOperation(int a, @XmlElement(name = "test") String b, Date c) {
98 return true;
99 }
100
101
102
103
104
105
106
107
108
109 static void doSomething(@SuppressWarnings("unused") boolean b, @SuppressWarnings("unused") String s) {
110 throw new IllegalStateException();
111 }
112
113
114
115
116
117
118 static String getStaticValue() {
119 return "real";
120 }
121
122
123
124
125
126
127 @Disabled("test")
128 boolean methodWhichCallsAnotherInTheSameClass() {
129 return simpleOperation(1, "internal", null);
130 }
131
132
133
134
135
136
137 String overridableMethod() {
138 return "base";
139 }
140 }
141
142
143
144
145 @Test
146 void mockStaticMethodViaClassArgument() {
147 new Expectations(Collaborator.class) {
148 {
149 Collaborator.doSomething(true, "test");
150 }
151 };
152
153
154 Collaborator.doSomething(true, "test");
155 }
156
157
158
159
160 @Test
161 void mockStaticMethodWithReturnValueViaClassArgument() {
162 new Expectations(Collaborator.class) {
163 {
164 Collaborator.getStaticValue();
165 result = "mocked_result";
166 }
167 };
168
169 assertEquals("mocked_result", Collaborator.getStaticValue());
170 }
171
172
173
174
175 @Test
176 void dynamicMockFullyVerified_verifyAllRecordedExpectationsButNotAllOfTheReplayedOnes() {
177 final Collaborator collaborator = new Collaborator(0);
178
179 new Expectations(collaborator) {
180 {
181 collaborator.setValue(1);
182 }
183 };
184
185 collaborator.setValue(1);
186 collaborator.setValue(2);
187
188
189 new FullVerifications() {
190
191
192 };
193 }
194
195
196
197
198 @Test
199 void dynamicMockFullyVerifiedInOrder_verifyAllRecordedExpectationsButNotAllOfTheReplayedOnes() {
200 final Collaborator collaborator = new Collaborator(0);
201
202 new Expectations(collaborator) {
203 {
204 collaborator.setValue(2);
205 collaborator.setValue(3);
206 }
207 };
208
209 collaborator.setValue(1);
210 collaborator.setValue(2);
211 collaborator.setValue(3);
212
213
214 new VerificationsInOrder() {
215 {
216
217 collaborator.setValue(2);
218 collaborator.setValue(3);
219 }
220 };
221 new FullVerifications() {
222 };
223 }
224
225
226
227
228 @Test
229 @ExpectedException(MissingInvocation.class)
230 void expectTwoInvocationsOnDynamicMockButReplayOnce() {
231 final Collaborator collaborator = new Collaborator();
232
233 new Expectations(collaborator) {
234 {
235 collaborator.getValue();
236 times = 2;
237 }
238 };
239
240 assertEquals(0, collaborator.getValue());
241 }
242
243
244
245
246 @Test
247 void expectOneInvocationOnDynamicMockButReplayTwice() {
248 final Collaborator collaborator = new Collaborator(1);
249
250 new Expectations(collaborator) {
251 {
252 collaborator.getValue();
253 times = 1;
254 }
255 };
256
257
258 assertEquals(0, collaborator.getValue());
259
260
261 Assertions.assertThrows(UnexpectedInvocation.class, () -> assertEquals(0, collaborator.getValue()));
262 }
263
264
265
266
267 @Test
268 void dynamicallyMockAnInstance() {
269 final Collaborator collaborator = new Collaborator(2);
270
271 new Expectations(collaborator) {
272 {
273 collaborator.simpleOperation(1, "", null);
274 result = false;
275 Collaborator.doSomething(anyBoolean, "test");
276 }
277 };
278
279
280 assertFalse(collaborator.simpleOperation(1, "", null));
281 Collaborator.doSomething(true, "test");
282
283
284 assertEquals(2, collaborator.getValue());
285 assertEquals(45, new Collaborator(45).value);
286 assertEquals(-1, new Collaborator().value);
287
288 try {
289 Collaborator.doSomething(false, null);
290 fail();
291 } catch (IllegalStateException ignore) {
292 }
293
294 new Verifications() {
295 {
296 collaborator.getValue();
297 times = 1;
298 }
299 };
300 }
301
302
303
304
305 @Test
306 void mockMethodInSameClass() {
307 final Collaborator collaborator = new Collaborator();
308
309 new Expectations(collaborator) {
310 {
311 collaborator.simpleOperation(1, anyString, null);
312 result = false;
313 }
314 };
315
316 assertFalse(collaborator.methodWhichCallsAnotherInTheSameClass());
317 assertTrue(collaborator.simpleOperation(2, "", null));
318 assertFalse(collaborator.simpleOperation(1, "", null));
319 }
320
321
322
323
324 static final class SubCollaborator extends Collaborator {
325
326
327
328
329 @SuppressWarnings("unused")
330 SubCollaborator() {
331 this(1);
332 }
333
334
335
336
337
338
339
340 SubCollaborator(int value) {
341 super(value);
342 }
343
344 @Override
345 String overridableMethod() {
346 return super.overridableMethod() + " overridden";
347 }
348
349
350
351
352
353
354 String format() {
355 return String.valueOf(value);
356 }
357
358
359
360
361 static void causeFailure() {
362 throw new RuntimeException();
363 }
364 }
365
366
367
368
369 @Test
370 void dynamicallyMockASubCollaboratorInstance() {
371 final SubCollaborator collaborator = new SubCollaborator();
372
373 new Expectations(collaborator) {
374 {
375 collaborator.getValue();
376 result = 5;
377 collaborator.format();
378 result = "test";
379 SubCollaborator.causeFailure();
380 }
381 };
382
383
384 assertEquals(5, collaborator.getValue());
385 SubCollaborator.causeFailure();
386 assertEquals("test", collaborator.format());
387
388
389 assertTrue(collaborator.simpleOperation(0, null, null));
390 assertEquals("1", new SubCollaborator().format());
391
392 try {
393 Collaborator.doSomething(true, null);
394 fail();
395 } catch (IllegalStateException ignore) {
396 }
397 }
398
399
400
401
402 interface Dependency {
403
404
405
406
407
408
409 boolean doSomething();
410
411
412
413
414
415
416
417
418
419 List<?> doSomethingElse(int n);
420 }
421
422
423
424
425 @Test
426 void dynamicallyMockAnAnonymousClassInstanceThroughTheImplementedInterface() {
427 final Collaborator collaborator = new Collaborator();
428
429 final Dependency dependency = new Dependency() {
430 @Override
431 public boolean doSomething() {
432 return false;
433 }
434
435 @Override
436 public List<?> doSomethingElse(int n) {
437 return null;
438 }
439 };
440
441 new Expectations(collaborator, dependency) {
442 {
443 collaborator.getValue();
444 result = 5;
445 dependency.doSomething();
446 result = true;
447 }
448 };
449
450
451 assertEquals(5, collaborator.getValue());
452 assertTrue(dependency.doSomething());
453
454
455 assertTrue(collaborator.simpleOperation(0, null, null));
456 assertNull(dependency.doSomethingElse(3));
457
458 new FullVerifications() {
459 {
460 dependency.doSomethingElse(anyInt);
461 collaborator.simpleOperation(0, null, null);
462 }
463 };
464 }
465
466
467
468
469 public interface AnotherInterface {
470 }
471
472
473
474
475 interface NonPublicInterface {
476 }
477
478
479
480
481
482
483
484
485
486 @Test
487 void attemptToUseDynamicMockingForInvalidTypes(@Mocked AnotherInterface publicInterfaceMock,
488 @Injectable NonPublicInterface nonPublicInterfaceMock) {
489 assertInvalidTypeForDynamicPartialMocking(new String[1]);
490 assertInvalidTypeForDynamicPartialMocking(123);
491 assertInvalidTypeForDynamicPartialMocking(true);
492 assertInvalidTypeForDynamicPartialMocking(2.5);
493 assertInvalidTypeForDynamicPartialMocking(publicInterfaceMock);
494 assertInvalidTypeForDynamicPartialMocking(nonPublicInterfaceMock);
495 }
496
497
498
499
500
501
502
503 void assertInvalidTypeForDynamicPartialMocking(Object object) {
504 try {
505 new Expectations(object) {
506 };
507 fail();
508 } catch (IllegalArgumentException e) {
509 assertTrue(e.getMessage().contains("partial mocking"));
510 }
511 }
512
513
514
515
516 @Test
517 void dynamicPartialMockingWithExactArgumentMatching() {
518 final Collaborator collaborator = new Collaborator();
519
520 new Expectations(collaborator) {
521 {
522 collaborator.simpleOperation(1, "s", null);
523 result = false;
524 }
525 };
526
527 assertFalse(collaborator.simpleOperation(1, "s", null));
528 assertTrue(collaborator.simpleOperation(2, "s", null));
529 assertTrue(collaborator.simpleOperation(1, "S", null));
530 assertTrue(collaborator.simpleOperation(1, "s", new Date()));
531 assertTrue(collaborator.simpleOperation(1, null, new Date()));
532 assertFalse(collaborator.simpleOperation(1, "s", null));
533
534 new FullVerifications() {
535 {
536 collaborator.simpleOperation(anyInt, null, null);
537 }
538 };
539 }
540
541
542
543
544 @Test
545 void dynamicPartialMockingWithFlexibleArgumentMatching() {
546 final Collaborator mock = new Collaborator();
547
548 new Expectations(mock) {
549 {
550 mock.simpleOperation(anyInt, withPrefix("s"), null);
551 result = false;
552 }
553 };
554
555 assertFalse(mock.simpleOperation(1, "sSs", null));
556 assertTrue(mock.simpleOperation(2, " s", null));
557 assertTrue(mock.simpleOperation(1, "S", null));
558 assertFalse(mock.simpleOperation(-1, "s", new Date()));
559 assertTrue(mock.simpleOperation(1, null, null));
560 assertFalse(mock.simpleOperation(0, "string", null));
561
562 Collaborator collaborator = new Collaborator();
563 assertTrue(collaborator.simpleOperation(1, "sSs", null));
564 assertTrue(collaborator.simpleOperation(-1, null, new Date()));
565 }
566
567
568
569
570 @Test
571 void dynamicPartialMockingWithInstanceSpecificMatching() {
572 final Collaborator collaborator1 = new Collaborator();
573 final Collaborator collaborator2 = new Collaborator(4);
574
575 new Expectations(collaborator1, collaborator2) {
576 {
577 collaborator1.getValue();
578 result = 3;
579 }
580 };
581
582 assertEquals(3, collaborator1.getValue());
583 assertEquals(4, collaborator2.getValue());
584
585 new VerificationsInOrder() {
586 {
587 collaborator1.getValue();
588 times = 1;
589 collaborator2.getValue();
590 times = 1;
591 }
592 };
593 }
594
595
596
597
598 @Test
599 void dynamicPartialMockingWithInstanceSpecificMatchingOnTwoInstancesOfSameClass() {
600 final Collaborator mock1 = new Collaborator();
601 final Collaborator mock2 = new Collaborator();
602
603 new Expectations(mock1, mock2) {
604 {
605 mock1.getValue();
606 result = 1;
607 mock2.getValue();
608 result = 2;
609 }
610 };
611
612 assertEquals(2, mock2.getValue());
613 assertEquals(1, mock1.getValue());
614 }
615
616
617
618
619 @Test
620 void methodWithNoRecordedExpectationCalledTwiceDuringReplay() {
621 final Collaborator collaborator = new Collaborator(123);
622
623 new Expectations(collaborator) {
624 };
625
626 assertEquals(123, collaborator.getValue());
627 assertEquals(123, collaborator.getValue());
628
629 new FullVerifications() {
630 {
631 collaborator.getValue();
632 times = 2;
633 }
634 };
635 }
636
637
638
639
640 static final class ClassWithNative {
641
642
643
644
645
646
647 int doSomething() {
648 return nativeMethod();
649 }
650
651
652
653
654
655
656 private native int nativeMethod();
657 }
658
659
660
661
662 @Test
663 @ExpectedException(UnsatisfiedLinkError.class)
664 void attemptToPartiallyMockNativeMethod() {
665 final ClassWithNative mock = new ClassWithNative();
666
667 new Expectations(mock) {
668 {
669
670
671 mock.nativeMethod();
672 }
673 };
674 }
675
676
677
678
679
680
681
682
683
684
685 @Test
686 void mockAnnotatedConstructor(@Mocked Collaborator mock) throws Exception {
687 Constructor<?> mockedConstructor = Collaborator.class.getDeclaredConstructor(int.class);
688
689 assertTrue(mockedConstructor.isAnnotationPresent(Deprecated.class));
690 assertTrue(mockedConstructor.getParameterAnnotations()[0][0] instanceof Deprecated);
691 }
692
693
694
695
696 static final class TestedClass {
697
698
699
700
701 TestedClass() {
702 this(true);
703 }
704
705
706
707
708
709
710
711 TestedClass(boolean value) {
712 initialize(value);
713 }
714
715
716
717
718
719
720
721 private void initialize(@SuppressWarnings("unused") boolean flag) {
722 }
723 }
724
725
726
727
728 static class BaseClass {
729
730
731
732
733
734
735 @SuppressWarnings("unused")
736 BaseClass(Object o) {
737 assert o != null;
738 }
739
740
741
742
743 BaseClass() {
744 }
745 }
746
747
748
749
750 static class SubClass extends BaseClass {
751 }
752
753
754
755
756 static class SubSubClass extends SubClass {
757 }
758
759
760
761
762
763
764
765 @Test
766 void mockClassIndirectlyExtendingBaseWhoseFirstConstructorHasMoreParametersThanTheSecondOne(
767 @Mocked SubSubClass mock) {
768 new SubClass();
769 }
770 }