1 package mockit;
2
3 import static java.util.Arrays.asList;
4 import static java.util.Collections.singletonList;
5
6 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
7 import static org.junit.jupiter.api.Assertions.assertEquals;
8 import static org.junit.jupiter.api.Assertions.assertFalse;
9 import static org.junit.jupiter.api.Assertions.assertNull;
10 import static org.junit.jupiter.api.Assertions.assertSame;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
12 import static org.junit.jupiter.api.Assertions.assertTrue;
13
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.LinkedList;
17 import java.util.List;
18
19 import mockit.internal.expectations.invocation.MissingInvocation;
20
21 import org.junit.jupiter.api.Test;
22
23
24
25
26 @SuppressWarnings("ConstantConditions")
27 final class WithCaptureTest {
28
29
30
31
32 public static class Person {
33
34
35 private String name;
36
37
38 private int age;
39
40
41
42
43 public Person() {
44 }
45
46
47
48
49
50
51
52
53
54 public Person(String name, int age) {
55 this.name = name;
56 this.age = age;
57 }
58
59
60
61
62
63
64 public String getName() {
65 return name;
66 }
67
68
69
70
71
72
73 public int getAge() {
74 return age;
75 }
76 }
77
78
79
80
81
82
83
84 public interface DAO<T> {
85
86
87
88
89
90
91 @SuppressWarnings("unused")
92 void create(T t);
93 }
94
95
96
97
98 @SuppressWarnings("UnusedParameters")
99 public static final class PersonDAO implements DAO<Person> {
100 @Override
101 public void create(Person p) {
102 }
103
104
105
106
107
108
109
110
111
112
113
114 public Person create(String name, int age) {
115 return new Person(name, age);
116 }
117
118
119
120
121
122
123
124 public void doSomething(Integer i) {
125 }
126
127
128
129
130
131
132
133 public void doSomething(boolean b) {
134 }
135
136
137
138
139
140
141
142 public void doSomething(Number n) {
143 }
144
145
146
147
148
149
150
151 public void doSomethingElse(Number n) {
152 }
153
154
155
156
157
158
159
160 public void doSomething(Number[] nums) {
161 }
162
163
164
165
166
167
168
169 public void doSomething(List<Integer> nums) {
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 public void doSomething(String s1, boolean b, String s2, double d, float f, long l, Object o, char c, byte bt,
197 short sh) {
198 }
199
200
201
202
203
204
205
206
207
208 void doSomething(String[] names, int[] ages) {
209 }
210
211
212
213
214
215
216
217
218
219
220
221 void doSomething(Float f1, float f2, boolean... flags) {
222 }
223
224
225
226
227
228
229
230
231
232 void doSomething(String name, Short age) {
233 }
234 }
235
236
237 @Mocked
238 PersonDAO dao;
239
240
241
242
243 @Test
244 void captureArgumentFromLastMatchingInvocationToLocalVariable() {
245 dao.create("Mary Jane", 10);
246 dao.create("John", 25);
247
248 new FullVerifications() {
249 {
250 int age;
251 dao.create(null, age = withCapture());
252 assertTrue(age >= 18);
253 }
254 };
255 }
256
257
258
259
260 @Test
261 void captureArgumentOfWrapperTypeToLocalVariableOfPrimitiveType() {
262 dao.doSomething(45);
263
264 new Verifications() {
265 {
266 int i;
267 dao.doSomething(i = withCapture());
268 assertEquals(45, i);
269 }
270 };
271 }
272
273
274
275
276 @Test
277 void captureNullArgumentOfWrapperTypeToLocalVariableOfSameWrapperType() {
278 dao.doSomething((Integer) null);
279
280 new Verifications() {
281 {
282 Integer i;
283 dao.doSomething(i = withCapture());
284 assertNull(i);
285 }
286 };
287 }
288
289
290
291
292 @Test
293 void captureArgumentOfReferenceTypeToLocalVariableOfPrimitiveType() {
294 dao.doSomething(123.0F);
295
296 new Verifications() {
297 {
298 float f;
299 dao.doSomething(f = withCapture());
300 assertEquals(123.0F, f, 0);
301 }
302 };
303 }
304
305
306
307
308 @Test
309 void captureNullIntoAListDuringVerification() {
310 dao.create(null);
311
312 new Verifications() {
313 {
314 List<Person> persons = new ArrayList<>();
315 dao.create(withCapture(persons));
316 assertEquals(1, persons.size());
317 assertNull(persons.get(0));
318 }
319 };
320 }
321
322
323
324
325 @Test
326 void captureArgumentToVariableOfSpecificSubtypeForSeparateInvocations() {
327 dao.doSomething(new BigInteger("9999"));
328 dao.doSomething((byte) -123);
329 dao.doSomething(123.0F);
330 dao.doSomething(1234L);
331 dao.doSomething(1234.5);
332
333 new Verifications() {
334 {
335 BigInteger bi;
336 dao.doSomething(bi = withCapture());
337 assertEquals(9999, bi.intValue());
338
339 Float f;
340 dao.doSomething(f = withCapture());
341 assertEquals(123.0F, f, 0);
342
343 long l;
344 dao.doSomething(l = withCapture());
345 assertEquals(1234L, l);
346
347 Double d;
348 dao.doSomething(d = withCapture());
349 assertEquals(1234.5, d, 0);
350
351 byte b;
352 dao.doSomething(b = withCapture());
353 assertEquals(-123, b);
354 }
355 };
356 }
357
358
359
360
361 @Test
362 void captureArrayArgumentsToVariablesWithSpecificElementSubtypes() {
363 final Integer[] ints = { 1, 2, 3 };
364 dao.doSomething(ints);
365
366 final Double[] doubles = { 1.0, 2.5, -3.2 };
367 dao.doSomething(doubles);
368
369 final BigInteger[] bigInts = { new BigInteger("12"), new BigInteger("45") };
370 dao.doSomething(bigInts);
371
372 new VerificationsInOrder() {
373 {
374 Integer[] capturedInts;
375 dao.doSomething(capturedInts = withCapture());
376 assertSame(ints, capturedInts);
377
378 Double[] capturedDoubles;
379 dao.doSomething(capturedDoubles = withCapture());
380 assertSame(doubles, capturedDoubles);
381
382 BigInteger[] capturedBigInts;
383 dao.doSomething(capturedBigInts = withCapture());
384 assertSame(bigInts, capturedBigInts);
385 }
386 };
387 }
388
389
390
391
392 @Test
393 void captureArgumentOfPrimitiveTypeToLocalVariableOfPrimitiveType() {
394 dao.doSomething(true);
395
396 new Verifications() {
397 {
398 boolean b;
399 dao.doSomething(b = withCapture());
400 assertTrue(b);
401 }
402 };
403 }
404
405
406
407
408 @Test
409 void captureArgumentOfPrimitiveTypeToLocalVariableOfReferenceType() {
410 dao.doSomething(true);
411
412 new Verifications() {
413 {
414 Boolean b;
415 dao.doSomething(b = withCapture());
416 assertTrue(b);
417 }
418 };
419 }
420
421
422
423
424 @Test
425 void captureArgumentsToLocalVariables() {
426 final Person p = new Person("John", 10);
427 dao.create(p);
428 dao.create("Mary Jane", 30);
429 dao.doSomething("test", true, "Test", 4.5, -2.3F, 123, p, 'g', (byte) 127, (short) -32767);
430
431 new Verifications() {
432 {
433 Person created;
434 dao.create(created = withCapture());
435 assertEquals("John", created.getName());
436 assertEquals(10, created.getAge());
437
438 String name;
439 int age;
440 dao.create(name = withCapture(), age = withCapture());
441 assertEquals("Mary Jane", name);
442 assertEquals(30, age);
443
444 String s1;
445 boolean b;
446 double d;
447 float f;
448 long l;
449 Object o;
450 char c;
451 byte bt;
452 short sh;
453 dao.doSomething(s1 = withCapture(), b = withCapture(), "Test", d = withCapture(), f = withCapture(),
454 l = withCapture(), o = withCapture(), c = withCapture(), bt = withCapture(),
455 sh = withCapture());
456 assertEquals("test", s1);
457 assertTrue(b);
458 assertEquals(4.5, d, 0);
459 assertEquals(-2.3, f, 0.001);
460 assertEquals(123, l);
461 assertSame(p, o);
462 assertEquals('g', c);
463 assertEquals(127, bt);
464 assertEquals(-32767, sh);
465 }
466 };
467 }
468
469
470
471
472 @Test
473 void attemptToCaptureArgumentsIntoFields() {
474 dao.doSomething(56);
475
476 new Verifications() {
477 final Integer i;
478
479 {
480 dao.doSomething(i = withCapture());
481 assertNull(i);
482 }
483 };
484 }
485
486
487
488
489 @Test
490 void captureFirstArgumentInTwoParameterMethod() {
491 final String name1 = "Ted";
492 final Short age = 15;
493 dao.doSomething(name1, age);
494
495 final String name2 = "Jane";
496 dao.doSomething(name2, age);
497
498 new VerificationsInOrder() {
499 {
500 String nameCapture;
501 dao.doSomething(nameCapture = withCapture(), age);
502 assertEquals(name1, nameCapture);
503
504 String strCapture;
505 dao.doSomething(strCapture = withCapture(), age);
506 assertEquals(name2, strCapture);
507 }
508 };
509 }
510
511
512
513
514 @Test
515 void captureArgumentsForInvocationAlreadyMatchedByRecordedExpectation() {
516 new Expectations() {
517 {
518 dao.doSomething(anyString, anyShort);
519 }
520 };
521
522 dao.doSomething("testing", (short) 15);
523
524 new Verifications() {
525 {
526 String s;
527 short i;
528 dao.doSomething(s = withCapture(), i = withCapture());
529 assertEquals("testing", s);
530 assertEquals(15, i);
531 }
532 };
533 }
534
535
536
537
538 @Test
539 void captureArgumentsFromConsecutiveMatchingInvocations() {
540 dao.doSomething((byte) 56);
541 dao.doSomething(123.4F);
542 dao.doSomething((short) -78);
543 dao.doSomething(91);
544 dao.doSomething(92);
545
546 final String[] names1 = { "Ted" };
547 final int[] ages1 = { 15, 46 };
548 dao.doSomething(names1, ages1);
549
550 final String[] names2 = { "Jane" };
551 final int[] ages2 = { 101 };
552 dao.doSomething(names2, ages2);
553
554 new VerificationsInOrder() {
555 {
556 byte bt;
557 dao.doSomething(bt = withCapture());
558 assertEquals(56, bt);
559
560 Number n;
561 dao.doSomething(n = withCapture());
562 assertEquals(123.4, n.floatValue(), 0.001);
563
564 short sh;
565 dao.doSomething(sh = withCapture());
566 assertEquals(-78, sh);
567
568 int i1;
569 dao.doSomething(i1 = withCapture());
570 assertEquals(91, i1);
571
572 Integer i2;
573 dao.doSomething(i2 = withCapture());
574 assertEquals(92, i2.intValue());
575
576 String[] namesCapture;
577 int[] agesCapture;
578 dao.doSomething(namesCapture = withCapture(), agesCapture = withCapture());
579 assertSame(names1, namesCapture);
580 assertSame(ages1, agesCapture);
581
582 dao.doSomething(namesCapture = withCapture(), agesCapture = withCapture());
583 assertSame(names2, namesCapture);
584 assertSame(ages2, agesCapture);
585 }
586 };
587 }
588
589
590
591
592 @Test
593 void captureArrayArguments() {
594 final String[] names = { "Ted", "Lisa" };
595 final int[] ages = { 67, 19 };
596 dao.doSomething(names, ages);
597
598 new Verifications() {
599 {
600 String[] capturedNames;
601 int[] capturedAges;
602 dao.doSomething(capturedNames = withCapture(), capturedAges = withCapture());
603
604 assertArrayEquals(names, capturedNames);
605 assertArrayEquals(ages, capturedAges);
606 }
607 };
608 }
609
610
611
612
613 @Test
614 void captureVarargsParameter() {
615 dao.doSomething(1.2F, 1.0F, true, false, true);
616 dao.doSomething(0.0F, 2.0F, false, true);
617 dao.doSomething(-2.0F, 3.0F);
618
619 new VerificationsInOrder() {
620 {
621 boolean[] flags;
622
623 dao.doSomething(anyFloat, 1.0F, flags = withCapture());
624 assertEquals(3, flags.length);
625 assertTrue(flags[0]);
626 assertFalse(flags[1]);
627 assertTrue(flags[2]);
628
629 dao.doSomething(null, 2.0F, flags = withCapture());
630 assertEquals(2, flags.length);
631 assertFalse(flags[0]);
632 assertTrue(flags[1]);
633
634 dao.doSomething(withAny(0.0F), 3.0F, flags = withCapture());
635 assertEquals(0, flags.length);
636 }
637 };
638 }
639
640
641
642
643 @Test
644 void captureArgumentsWhileMixingAnyFieldsAndLiteralValuesAndCallsToOtherMethods() {
645 final double d = 4.5;
646 final long l = 123;
647 dao.doSomething("Test", true, "data", d, 12.25F, l, "testing", '9', (byte) 11, (short) 5);
648
649 new Verifications() {
650 {
651 float f;
652 String s;
653 byte b;
654
655
656 dao.doSomething(null, anyBoolean, getData(), Math.abs(-d), f = withCapture(), Long.parseLong("" + l),
657 s = withCapture(), Character.forDigit(9, 10), b = withCapture(), anyShort);
658
659 assertEquals(12.25F, f, 0);
660 assertEquals("testing", s);
661 assertEquals(11, b);
662 }
663 };
664 }
665
666
667
668
669
670
671 private String getData() {
672 return "data";
673 }
674
675
676
677
678 @Test
679 void captureArgumentsIntoListInExpectationBlock() {
680 final List<Person> personsCreated = new ArrayList<>();
681 final List<String> personNames = new LinkedList<>();
682 final List<Integer> personAges = new LinkedList<>();
683
684 new Expectations() {
685 {
686 dao.create(withCapture(personsCreated));
687 dao.create(withCapture(personNames), withCapture(personAges));
688 }
689 };
690
691 dao.create(new Person("John", 10));
692 assertEquals(1, personsCreated.size());
693 Person first = personsCreated.get(0);
694 assertEquals("John", first.getName());
695 assertEquals(10, first.getAge());
696
697 dao.create(new Person("Jane", 20));
698 assertEquals(2, personsCreated.size());
699 Person second = personsCreated.get(1);
700 assertEquals("Jane", second.getName());
701 assertEquals(20, second.getAge());
702
703 dao.create("Mary Jane", 35);
704 assertEquals(1, personNames.size());
705 assertEquals("Mary Jane", personNames.get(0));
706 assertEquals(1, personAges.size());
707 assertEquals(35, personAges.get(0).intValue());
708 }
709
710
711
712
713 @Test
714 void captureArgumentsIntoListInVerificationBlock() {
715 dao.create(new Person("John", 10));
716 dao.create("Mary Jane", 35);
717 dao.create("", 56);
718 dao.create(new Person("Jane", 20));
719 dao.create("Daisy Jones", 6);
720
721 new Verifications() {
722 final List<Person> created = new ArrayList<>();
723 final List<Integer> ages = new ArrayList<>();
724
725 {
726 dao.create("", withCapture(ages));
727 assertEquals(singletonList(56), ages);
728
729 dao.create(withCapture(created));
730 assertEquals(2, created.size());
731
732 Person first = created.get(0);
733 assertEquals("John", first.getName());
734 assertEquals(10, first.getAge());
735
736 Person second = created.get(1);
737 assertEquals("Jane", second.getName());
738 assertEquals(20, second.getAge());
739
740 ages.clear();
741 dao.create(withSubstring(" "), withCapture(ages));
742 times = 2;
743 assertEquals(asList(35, 6), ages);
744 }
745 };
746 }
747
748
749
750
751
752
753
754 @Test
755 void captureNewedInstance(@Mocked Person mockedPerson) {
756 Person p = new Person();
757 dao.create(p);
758
759 new Verifications() {
760 {
761 Person newInstance = withCapture(new Person()).get(0);
762
763 Person capturedPerson;
764 dao.create(capturedPerson = withCapture());
765
766 assertSame(newInstance, capturedPerson);
767 }
768 };
769 }
770
771
772
773
774
775
776
777 @Test
778 void captureMultipleNewInstances(@Mocked Person mockedPerson) {
779 dao.create(new Person("Paul", 10));
780 dao.create(new Person("Mary", 15));
781 dao.create(new Person("Joe", 20));
782
783 new Verifications() {
784 {
785 List<Person> personsInstantiated = withCapture(new Person(anyString, anyInt));
786
787 List<Person> personsCreated = new ArrayList<>();
788 dao.create(withCapture(personsCreated));
789
790
791 assertEquals(personsInstantiated, personsCreated);
792 }
793 };
794 }
795
796
797
798
799
800
801
802 @Test
803 void attemptToCaptureNewInstanceWhenThereWasNone(@Mocked Person mockedPerson) {
804 Throwable exception = assertThrows(MissingInvocation.class, () -> {
805
806 dao.create("test", 14);
807
808 new Verifications() {
809 {
810 List<Person> newInstances = withCapture(new Person());
811 times = 0;
812 assertTrue(newInstances.isEmpty());
813
814 withCapture(new Person(anyString, anyInt));
815 }
816 };
817 });
818 assertTrue(exception.getMessage().contains("Person(any String, any int)"));
819 }
820
821
822
823
824
825
826
827 @Test
828 void captureTwoSetsOfNewInstancesOfTheSameType(@Mocked Person mockedPerson) {
829
830 final Person p1 = new Person();
831
832
833 final Person p2 = new Person("Paul", 10);
834 final Person p3 = new Person("Mary", 15);
835
836 new Verifications() {
837 {
838 List<Person> persons1 = withCapture(new Person(anyString, anyInt));
839 assertEquals(asList(p2, p3), persons1);
840
841 List<Person> persons2 = withCapture(new Person());
842 assertEquals(singletonList(p1), persons2);
843 }
844 };
845 }
846
847
848
849
850
851
852
853 @Test
854 void captureNewInstancesAfterVerifyingNewInstanceOfDifferentType(@Mocked Person mockedPerson) {
855 new PersonDAO();
856 final Person p1 = new Person("Paul", 10);
857 final Person p2 = new Person("Mary", 10);
858
859 new Verifications() {
860 {
861 new PersonDAO();
862
863 List<Person> persons = withCapture(new Person(anyString, 10));
864 assertEquals(asList(p1, p2), persons);
865 }
866 };
867 }
868
869
870
871
872 @Test
873 void attemptToCaptureArgumentForInvocationThatNeverOccurred_unordered() {
874 Throwable exception = assertThrows(MissingInvocation.class, () -> {
875
876 new Verifications() {
877 {
878 Person p;
879 dao.create(p = withCapture());
880 times = 1;
881 assertEquals("...", p.getName());
882 }
883 };
884 });
885 assertTrue(exception.getMessage().contains("any " + Person.class.getName()));
886 }
887
888
889
890
891 @Test
892 void attemptToCaptureArgumentForInvocationThatNeverOccurred_ordered() {
893 assertThrows(MissingInvocation.class, () -> {
894
895 new VerificationsInOrder() {
896 {
897 Person p;
898 dao.create(p = withCapture());
899 times = 1;
900 assertEquals("...", p.getName());
901 }
902 };
903 });
904 }
905
906
907
908
909 static class ClassWithVarargsMethod {
910
911
912
913
914
915
916
917
918 @SuppressWarnings("unused")
919 void varargsMethod(String s, String... values) {
920 }
921 }
922
923
924
925
926
927
928
929 @Test
930 void captureVarargsValuesFromAllInvocations(@Mocked final ClassWithVarargsMethod mock) {
931 final String[] expectedValues1 = { "a", "b" };
932 mock.varargsMethod("First", expectedValues1);
933
934 final String[] expectedValues2 = { "1", "2" };
935 mock.varargsMethod("Second", expectedValues2);
936
937 new Verifications() {
938 {
939 List<String> capturedNames = new ArrayList<>();
940 List<String[]> capturedValues = new ArrayList<>();
941
942 mock.varargsMethod(withCapture(capturedNames), withCapture(capturedValues));
943
944 assertEquals(asList("First", "Second"), capturedNames);
945 assertArrayEquals(expectedValues1, capturedValues.get(0));
946 assertArrayEquals(expectedValues2, capturedValues.get(1));
947 }
948 };
949 }
950
951
952
953
954 @Test
955 void captureArgumentsIntoAListOfASubtypeOfTheCapturedParameterType() {
956 dao.doSomethingElse(1);
957 dao.doSomethingElse(2.0);
958 dao.doSomethingElse(3);
959
960 final List<Integer> expectedValues = asList(1, 3);
961
962 new Verifications() {
963 {
964 List<Integer> onlyIntegers = new ArrayList<>();
965 dao.doSomethingElse(withCapture(onlyIntegers));
966
967 assertEquals(expectedValues, onlyIntegers);
968 }
969 };
970 }
971
972
973
974
975 @Test
976 void captureListArgumentsFromMultipleInvocations() {
977 final List<Integer> integers1 = asList(1, 2, 3);
978 dao.doSomething(integers1);
979
980 final List<Integer> integers2 = asList(4, 5);
981 dao.doSomething(integers2);
982
983 new Verifications() {
984 {
985 List<List<Integer>> captures = new ArrayList<>();
986 dao.doSomething(withCapture(captures));
987 assertEquals(integers1, captures.get(0));
988 assertEquals(integers2, captures.get(1));
989 }
990 };
991 }
992 }