View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit;
7   
8   import static java.util.Arrays.asList;
9   
10  import static org.junit.jupiter.api.Assertions.assertEquals;
11  import static org.junit.jupiter.api.Assertions.assertFalse;
12  import static org.junit.jupiter.api.Assertions.assertThrows;
13  import static org.junit.jupiter.api.Assertions.assertTrue;
14  
15  import java.util.ArrayList;
16  import java.util.Date;
17  import java.util.List;
18  
19  import mockit.integration.junit5.JMockitExtension;
20  import mockit.internal.expectations.invocation.MissingInvocation;
21  
22  import org.junit.jupiter.api.Test;
23  import org.junit.jupiter.api.extension.ExtendWith;
24  
25  /**
26   * The Class ExpectationsWithSomeArgMatchersRecordedTest.
27   */
28  @ExtendWith(JMockitExtension.class)
29  class ExpectationsWithSomeArgMatchersRecordedTest {
30  
31      /**
32       * The Class Dependency.
33       */
34      static class Dependency {
35  
36          /** The value. */
37          private final int value;
38  
39          /**
40           * Instantiates a new dependency.
41           */
42          Dependency() {
43              value = 0;
44          }
45  
46          /**
47           * Instantiates a new dependency.
48           *
49           * @param value
50           *            the value
51           */
52          Dependency(int value) {
53              this.value = value;
54          }
55  
56          @Override
57          public boolean equals(Object obj) {
58              return obj instanceof Dependency && value == ((Dependency) obj).value;
59          }
60  
61          @Override
62          public int hashCode() {
63              return value;
64          }
65      }
66  
67      /**
68       * The Class Collaborator.
69       */
70      @SuppressWarnings({ "SameParameterValue", "unused" })
71      static class Collaborator {
72  
73          /**
74           * Sets the value.
75           *
76           * @param value
77           *            the new value
78           */
79          void setValue(int value) {
80          }
81  
82          /**
83           * Sets the value.
84           *
85           * @param value
86           *            the new value
87           */
88          void setValue(double value) {
89          }
90  
91          /**
92           * Sets the value.
93           *
94           * @param value
95           *            the new value
96           */
97          void setValue(float value) {
98          }
99  
100         /**
101          * Sets the value.
102          *
103          * @param value
104          *            the value
105          *
106          * @return the string
107          */
108         String setValue(String value) {
109             return "";
110         }
111 
112         /**
113          * Sets the values.
114          *
115          * @param value1
116          *            the value 1
117          * @param value2
118          *            the value 2
119          * @param value3
120          *            the value 3
121          * @param value4
122          *            the value 4
123          */
124         void setValues(long value1, byte value2, double value3, short value4) {
125         }
126 
127         /**
128          * Boolean values.
129          *
130          * @param value1
131          *            the value 1
132          * @param value2
133          *            the value 2
134          * @param value3
135          *            the value 3
136          * @param value4
137          *            the value 4
138          *
139          * @return true, if successful
140          */
141         boolean booleanValues(long value1, byte value2, double value3, short value4) {
142             return true;
143         }
144 
145         /**
146          * Static set values.
147          *
148          * @param value1
149          *            the value 1
150          * @param value2
151          *            the value 2
152          * @param value3
153          *            the value 3
154          * @param value4
155          *            the value 4
156          */
157         static void staticSetValues(long value1, byte value2, double value3, short value4) {
158         }
159 
160         /**
161          * Static long values.
162          *
163          * @param value1
164          *            the value 1
165          * @param value2
166          *            the value 2
167          * @param value3
168          *            the value 3
169          * @param value4
170          *            the value 4
171          *
172          * @return the long
173          */
174         static long staticLongValues(long value1, byte value2, double value3, short value4) {
175             return -2;
176         }
177 
178         /**
179          * Do something.
180          *
181          * @param src
182          *            the src
183          *
184          * @return the int
185          */
186         int doSomething(Dependency src) {
187             return -1;
188         }
189 
190         /**
191          * Do something.
192          *
193          * @param src
194          *            the src
195          * @param s
196          *            the s
197          *
198          * @return the int
199          */
200         int doSomething(Dependency src, String s) {
201             return -1;
202         }
203 
204         /**
205          * Do something.
206          *
207          * @param src
208          *            the src
209          * @param s
210          *            the s
211          *
212          * @return the int
213          */
214         int doSomething(Dependency src, String... s) {
215             return -1;
216         }
217 
218         /**
219          * Simple operation.
220          *
221          * @param a
222          *            the a
223          * @param b
224          *            the b
225          */
226         final void simpleOperation(int a, String b) {
227         }
228 
229         /**
230          * Simple operation.
231          *
232          * @param a
233          *            the a
234          * @param b
235          *            the b
236          * @param c
237          *            the c
238          */
239         final void simpleOperation(int a, String b, Date c) {
240         }
241 
242         /**
243          * Another operation.
244          *
245          * @param b
246          *            the b
247          * @param l
248          *            the l
249          *
250          * @return the long
251          */
252         long anotherOperation(byte b, Long l) {
253             return -1;
254         }
255 
256         /**
257          * Static void method.
258          *
259          * @param l
260          *            the l
261          * @param c
262          *            the c
263          * @param d
264          *            the d
265          */
266         static void staticVoidMethod(long l, char c, double d) {
267         }
268 
269         /**
270          * Static boolean method.
271          *
272          * @param b
273          *            the b
274          * @param s
275          *            the s
276          * @param array
277          *            the array
278          *
279          * @return true, if successful
280          */
281         static boolean staticBooleanMethod(boolean b, String s, int[] array) {
282             return false;
283         }
284 
285         /**
286          * Method with array parameters.
287          *
288          * @param c
289          *            the c
290          * @param s
291          *            the s
292          * @param matrix
293          *            the matrix
294          */
295         void methodWithArrayParameters(char[][] c, String[] s, Object[][][] matrix) {
296         }
297 
298         /**
299          * Method with many parameters.
300          *
301          * @param b1
302          *            the b 1
303          * @param s1
304          *            the s 1
305          * @param i1
306          *            the i 1
307          * @param l1
308          *            the l 1
309          * @param str1
310          *            the str 1
311          * @param bo1
312          *            the bo 1
313          * @param f1
314          *            the f 1
315          * @param d1
316          *            the d 1
317          * @param ii1
318          *            the ii 1
319          * @param ss1
320          *            the ss 1
321          * @param b2
322          *            the b 2
323          * @param s2
324          *            the s 2
325          * @param i2
326          *            the i 2
327          * @param l2
328          *            the l 2
329          * @param str2
330          *            the str 2
331          * @param bo2
332          *            the bo 2
333          * @param f2
334          *            the f 2
335          * @param d2
336          *            the d 2
337          * @param ii2
338          *            the ii 2
339          * @param ss2
340          *            the ss 2
341          * @param c
342          *            the c
343          */
344         void methodWithManyParameters(byte b1, short s1, int i1, long l1, String str1, boolean bo1, float f1, double d1,
345                 int[] ii1, String[] ss1, byte b2, short s2, int i2, long l2, String str2, boolean bo2, float f2,
346                 double d2, int[] ii2, String[] ss2, char c) {
347         }
348     }
349 
350     /** The mock. */
351     @Mocked
352     Collaborator mock;
353 
354     /**
355      * Use matcher only for one argument.
356      */
357     @Test
358     void useMatcherOnlyForOneArgument() {
359         final Object o = new Object();
360 
361         new Expectations() {
362             {
363                 mock.simpleOperation(withEqual(1), "", null);
364                 mock.simpleOperation(withNotEqual(1), null, (Date) withNull());
365                 mock.simpleOperation(12, "arg", (Date) withNotNull());
366 
367                 mock.anotherOperation((byte) 0, anyLong);
368                 result = 123L;
369                 mock.anotherOperation(anyByte, 5L);
370                 result = -123L;
371 
372                 Collaborator.staticVoidMethod(34L, anyChar, 5.0);
373                 Collaborator.staticBooleanMethod(true, withSuffix("end"), null);
374                 result = true;
375                 Collaborator.staticBooleanMethod(true, "", new int[] { 1, 2, 3 });
376                 result = true;
377 
378                 char[][] chars = { { 'a', 'b' }, { 'X', 'Y', 'Z' } };
379                 Object[][][] matrix = { null, { { 1, 'X', "test" } }, { { o } } };
380                 mock.methodWithArrayParameters(chars, (String[]) any, matrix);
381             }
382         };
383 
384         mock.simpleOperation(1, "", null);
385         mock.simpleOperation(2, "str", null);
386         mock.simpleOperation(1, "", null);
387         mock.simpleOperation(12, "arg", new Date());
388 
389         assertEquals(123L, mock.anotherOperation((byte) 0, 5L));
390         assertEquals(-123L, mock.anotherOperation((byte) 3, 5L));
391 
392         Collaborator.staticVoidMethod(34L, '8', 5.0);
393         assertTrue(Collaborator.staticBooleanMethod(true, "start-end", null));
394         assertTrue(Collaborator.staticBooleanMethod(true, "", new int[] { 1, 2, 3 }));
395 
396         mock.methodWithArrayParameters(new char[][] { { 'a', 'b' }, { 'X', 'Y', 'Z' } }, null,
397                 new Object[][][] { null, { { 1, 'X', "test" } }, { { o } } });
398     }
399 
400     /**
401      * Use matcher only for first argument with unexpected replay value.
402      */
403     @Test
404     void useMatcherOnlyForFirstArgumentWithUnexpectedReplayValue() {
405         assertThrows(MissingInvocation.class, () -> {
406 
407             mock.simpleOperation(2, "", null);
408 
409             new Verifications() {
410                 {
411                     mock.simpleOperation(withEqual(1), "", null);
412                 }
413             };
414         });
415     }
416 
417     /**
418      * Use matcher only for second argument with unexpected replay value.
419      */
420     @Test
421     void useMatcherOnlyForSecondArgumentWithUnexpectedReplayValue() {
422         assertThrows(MissingInvocation.class, () -> {
423 
424             mock.simpleOperation(1, "Xyz", null);
425 
426             new Verifications() {
427                 {
428                     mock.simpleOperation(1, withPrefix("arg"), null);
429                 }
430             };
431         });
432     }
433 
434     /**
435      * Use matcher only for last argument with unexpected replay value.
436      */
437     @Test
438     void useMatcherOnlyForLastArgumentWithUnexpectedReplayValue() {
439         assertThrows(MissingInvocation.class, () -> {
440 
441             mock.simpleOperation(12, "arg", null);
442 
443             new Verifications() {
444                 {
445                     mock.simpleOperation(12, "arg", (Date) withNotNull());
446                 }
447             };
448         });
449     }
450 
451     /**
452      * Use matchers for parameters of all sizes.
453      */
454     @Test
455     void useMatchersForParametersOfAllSizes() {
456         new Expectations() {
457             {
458                 mock.setValues(123L, withEqual((byte) 5), 6.4, withNotEqual((short) 14));
459                 mock.booleanValues(12L, (byte) 4, withEqual(6.0, 0.1), withEqual((short) 14));
460                 Collaborator.staticSetValues(withNotEqual(1L), (byte) 4, 6.1, withEqual((short) 3));
461                 Collaborator.staticLongValues(12L, anyByte, withEqual(6.1), (short) 4);
462             }
463         };
464 
465         mock.setValues(123L, (byte) 5, 6.4, (short) 41);
466         assertFalse(mock.booleanValues(12L, (byte) 4, 6.1, (short) 14));
467         Collaborator.staticSetValues(2L, (byte) 4, 6.1, (short) 3);
468         assertEquals(0L, Collaborator.staticLongValues(12L, (byte) -7, 6.1, (short) 4));
469     }
470 
471     /**
472      * Use any int field.
473      */
474     @Test
475     void useAnyIntField() {
476         new Expectations() {
477             {
478                 mock.setValue(anyInt);
479             }
480         };
481 
482         mock.setValue(1);
483     }
484 
485     /**
486      * Use any string field.
487      */
488     @Test
489     void useAnyStringField() {
490         new Expectations() {
491             {
492                 mock.setValue(anyString);
493                 returns("one", "two");
494             }
495         };
496 
497         assertEquals("one", mock.setValue("test"));
498         assertEquals("two", mock.setValue(""));
499         assertEquals("two", mock.setValue(null));
500     }
501 
502     /**
503      * Use several any fields.
504      */
505     @Test
506     void useSeveralAnyFields() {
507         final Date now = new Date();
508 
509         new Expectations() {
510             {
511                 mock.simpleOperation(anyInt, null, null);
512                 mock.simpleOperation(anyInt, "test", null);
513                 mock.simpleOperation(3, "test2", null);
514                 mock.simpleOperation(-1, null, (Date) any);
515                 mock.simpleOperation(1, anyString, now);
516 
517                 Collaborator.staticSetValues(2L, anyByte, 0.0, anyShort);
518 
519                 // noinspection ConstantConditions
520                 mock.methodWithManyParameters(anyByte, anyShort, anyInt, anyLong, anyString, anyBoolean, anyFloat,
521                         anyDouble, (int[]) any, (String[]) any, anyByte, anyShort, anyInt, anyLong, anyString,
522                         anyBoolean, anyFloat, anyDouble, (int[]) any, (String[]) any, anyChar);
523             }
524         };
525 
526         mock.simpleOperation(2, "abc", now);
527         mock.simpleOperation(5, "test", null);
528         mock.simpleOperation(3, "test2", null);
529         mock.simpleOperation(-1, "Xyz", now);
530         mock.simpleOperation(1, "", now);
531 
532         Collaborator.staticSetValues(2, (byte) 1, 0, (short) 2);
533 
534         mock.methodWithManyParameters((byte) 1, (short) 2, 3, 4L, "5", false, 7.0F, 8.0, null, null, (byte) 10,
535                 (short) 20, 30, 40L, "50", true, 70.0F, 80.0, null, null, 'x');
536     }
537 
538     /**
539      * Use with methods mixed with any fields.
540      */
541     @Test
542     void useWithMethodsMixedWithAnyFields() {
543         mock.simpleOperation(2, "abc", new Date());
544         mock.simpleOperation(5, "test", null);
545         mock.simpleOperation(3, "test2", null);
546         mock.simpleOperation(-1, "Xyz", new Date());
547         mock.simpleOperation(1, "", new Date());
548 
549         new FullVerifications() {
550             {
551                 mock.simpleOperation(anyInt, null, (Date) any);
552                 mock.simpleOperation(anyInt, withEqual("test"), null);
553                 mock.simpleOperation(3, withPrefix("test"), (Date) any);
554                 mock.simpleOperation(-1, anyString, (Date) any);
555                 mock.simpleOperation(1, anyString, (Date) withNotNull());
556             }
557         };
558     }
559 
560     /**
561      * The Interface Scheduler.
562      */
563     public interface Scheduler {
564         /**
565          * Gets the alerts.
566          *
567          * @param o
568          *            the o
569          * @param i
570          *            the i
571          * @param b
572          *            the b
573          *
574          * @return the alerts
575          */
576         List<String> getAlerts(Object o, int i, boolean b);
577     }
578 
579     /**
580      * Use matchers in invocations to interface methods.
581      *
582      * @param scheduler
583      *            the scheduler
584      */
585     @Test
586     void useMatchersInInvocationsToInterfaceMethods(@Mocked final Scheduler scheduler) {
587         new Expectations() {
588             {
589                 scheduler.getAlerts(any, 1, anyBoolean);
590                 result = asList("A", "b");
591             }
592         };
593 
594         assertEquals(2, scheduler.getAlerts("123", 1, true).size());
595     }
596 
597     // Tests for the matching of expectations to instances created during replay
598     // ///////////////////////////////////////////////////////////
599 
600     /**
601      * Record expectations for mocked objects instantiated inside SUT.
602      *
603      * @param dep
604      *            the dep
605      */
606     @Test
607     void recordExpectationsForMockedObjectsInstantiatedInsideSUT(@Mocked Dependency dep) {
608         new Expectations() {
609             {
610                 Dependency src1 = new Dependency(1);
611                 Dependency src2 = new Dependency(2);
612                 mock.doSomething(src1);
613                 result = 1;
614                 times = 2;
615                 mock.doSomething(src2);
616                 result = 2;
617                 times = 2;
618             }
619         };
620 
621         Dependency src1 = new Dependency(1);
622         Dependency src2 = new Dependency(2);
623         Dependency src3 = new Dependency(1);
624         Dependency src4 = new Dependency(2);
625 
626         assertEquals(1, mock.doSomething(src1));
627         assertEquals(2, mock.doSomething(src2));
628         assertEquals(1, mock.doSomething(src3));
629         assertEquals(2, mock.doSomething(src4));
630     }
631 
632     /**
633      * Verify unordered expectations for mocked objects instantiated inside SUT.
634      */
635     @Test
636     void verifyUnorderedExpectationsForMockedObjectsInstantiatedInsideSUT() {
637         Dependency src1 = new Dependency(1);
638         Dependency src2 = new Dependency(2);
639         Dependency src3 = new Dependency(1);
640         Dependency src4 = new Dependency(2);
641 
642         mock.doSomething(src1);
643         mock.doSomething(src2);
644         mock.doSomething(src3);
645         mock.doSomething(src4);
646 
647         final List<Dependency> dependencies = new ArrayList<>();
648         new Verifications() {
649             {
650                 mock.doSomething(withCapture(dependencies));
651                 times = 4;
652             }
653         };
654 
655         int i1 = dependencies.indexOf(new Dependency(1));
656         int l1 = dependencies.lastIndexOf(new Dependency(1));
657         assertTrue(i1 >= 0);
658         assertTrue(l1 >= 0 && l1 != i1);
659 
660         int i2 = dependencies.indexOf(new Dependency(2));
661         int l2 = dependencies.lastIndexOf(new Dependency(2));
662         assertTrue(i2 >= 0);
663         assertTrue(l2 >= 0 && l2 != i2);
664     }
665 
666     /**
667      * Verify ordered expectations for mocked objects instantiated inside SUT.
668      */
669     @Test
670     void verifyOrderedExpectationsForMockedObjectsInstantiatedInsideSUT() {
671         Dependency src1 = new Dependency(1);
672         Dependency src2 = new Dependency(2);
673         Dependency src3 = new Dependency(2);
674         Dependency src4 = new Dependency(1);
675 
676         mock.doSomething(src1);
677         mock.doSomething(src2);
678         mock.doSomething(src3);
679         mock.doSomething(src4);
680 
681         new VerificationsInOrder() {
682             {
683                 Dependency dep1 = new Dependency(1);
684                 Dependency dep2 = new Dependency(2);
685                 mock.doSomething(dep1);
686                 mock.doSomething(dep2);
687                 times = 2;
688                 mock.doSomething(dep1);
689             }
690         };
691     }
692 
693     /**
694      * Record expectation with matcher and regular argument matching mocked object instantiated inside SUT.
695      *
696      * @param dep
697      *            the dep
698      */
699     @Test
700     void recordExpectationWithMatcherAndRegularArgumentMatchingMockedObjectInstantiatedInsideSUT(
701             @Mocked Dependency dep) {
702         final List<Dependency> dependencies = new ArrayList<>();
703 
704         new Expectations() {
705             {
706                 Dependency src = new Dependency();
707                 dependencies.add(src);
708             }
709         };
710 
711         new Expectations() {
712             {
713                 Dependency firstDep = dependencies.get(0);
714                 mock.doSomething(firstDep, anyString);
715                 result = 123;
716             }
717         };
718 
719         Dependency src = new Dependency();
720         int i = mock.doSomething(src, "test");
721 
722         assertEquals(123, i);
723     }
724 
725     /**
726      * Record varargs expectation with matcher and regular argument matching mocked object instantiated inside SUT.
727      *
728      * @param dep
729      *            the dep
730      */
731     @Test
732     void recordVarargsExpectationWithMatcherAndRegularArgumentMatchingMockedObjectInstantiatedInsideSUT(
733             @Mocked Dependency dep) {
734         final List<Dependency> dependencies = new ArrayList<>();
735 
736         new Expectations() {
737             {
738                 Dependency src = new Dependency();
739                 dependencies.add(src);
740             }
741         };
742 
743         new Expectations() {
744             {
745                 Dependency firstDep = dependencies.get(0);
746                 mock.doSomething(firstDep, (String[]) any);
747                 result = 123;
748             }
749         };
750 
751         Dependency src = new Dependency();
752         int i = mock.doSomething(src, "a", "b");
753 
754         assertEquals(123, i);
755     }
756 
757     /**
758      * Record instantiation expectations for mocked objects instantiated inside SUT.
759      *
760      * @param anyDep
761      *            the any dep
762      */
763     @Test
764     void recordInstantiationExpectationsForMockedObjectsInstantiatedInsideSUT(@Mocked Dependency anyDep) {
765         new Expectations() {
766             {
767                 Dependency dep1 = new Dependency(1);
768                 Dependency dep2 = new Dependency(2);
769                 mock.doSomething(dep1);
770                 result = 1;
771                 times = 2;
772                 mock.doSomething(dep2);
773                 result = 2;
774                 times = 2;
775             }
776         };
777 
778         Dependency src1 = new Dependency(1);
779         Dependency src2 = new Dependency(2);
780         Dependency src3 = new Dependency(1);
781         Dependency src4 = new Dependency(2);
782 
783         assertEquals(1, mock.doSomething(src1));
784         assertEquals(2, mock.doSomething(src2));
785         assertEquals(1, mock.doSomething(src3));
786         assertEquals(2, mock.doSomething(src4));
787     }
788 
789     // The following tests failed only when compiled with the Eclipse compiler
790     // /////////////////////////////////////////////////////////////
791 
792     /**
793      * Expectation with matchers spanning multiple lines.
794      */
795     @Test
796     void expectationWithMatchersSpanningMultipleLines() {
797         new Expectations() {
798             {
799                 mock.simpleOperation(1, (String) withNull());
800             }
801         };
802 
803         mock.simpleOperation(1, null);
804     }
805 
806     /**
807      * Expectation with matcher in second line and constant argument in third line.
808      */
809     @Test
810     void expectationWithMatcherInSecondLineAndConstantArgumentInThirdLine() {
811         new Expectations() {
812             {
813                 mock.simpleOperation(anyInt, "test");
814             }
815         };
816 
817         mock.simpleOperation(123, "test");
818     }
819 
820     /**
821      * Expectations with partial matchers in every combination for method with three parameters.
822      */
823     @Test
824     void expectationsWithPartialMatchersInEveryCombinationForMethodWithThreeParameters() {
825         final Date now = new Date();
826 
827         mock.simpleOperation(123, "test", null);
828         mock.simpleOperation(-2, "", now);
829         mock.simpleOperation(0, "test", now);
830         mock.simpleOperation(1, "test", null);
831         mock.simpleOperation(0, "test", null);
832         mock.simpleOperation(-3, "xyz", now);
833         mock.simpleOperation(123, null, now);
834         mock.simpleOperation(123, "", null);
835 
836         new VerificationsInOrder() {
837             {
838                 // Expectations with one matcher:
839                 mock.simpleOperation(anyInt, "test", null);
840                 mock.simpleOperation(-2, anyString, null);
841                 mock.simpleOperation(0, "test", (Date) withNotNull());
842                 mock.simpleOperation(1, null, (Date) withNull());
843                 mock.simpleOperation(0, "test", (Date) any);
844 
845                 // Expectations with two matchers:
846                 mock.simpleOperation(-3, anyString, (Date) any);
847                 mock.simpleOperation(withNotEqual(0), anyString, now);
848                 mock.simpleOperation(anyInt, "", (Date) any);
849             }
850         };
851     }
852 }