View Javadoc
1   package mockit;
2   
3   import static java.util.Arrays.asList;
4   
5   import static org.junit.jupiter.api.Assertions.assertEquals;
6   import static org.junit.jupiter.api.Assertions.assertNotNull;
7   import static org.junit.jupiter.api.Assertions.assertNull;
8   import static org.junit.jupiter.api.Assertions.assertTrue;
9   import static org.junit.jupiter.api.Assertions.fail;
10  
11  import java.io.IOException;
12  import java.util.ArrayList;
13  import java.util.List;
14  import java.util.concurrent.AbstractExecutorService;
15  
16  import org.junit.jupiter.api.Test;
17  
18  /**
19   * The Class DelegateInvocationProceedTest.
20   */
21  final class DelegateInvocationProceedTest {
22  
23      /**
24       * The Class BaseClassToBeMocked.
25       */
26      public static class BaseClassToBeMocked {
27  
28          /** The name. */
29          protected String name;
30  
31          /**
32           * Gets the name.
33           *
34           * @return the name
35           */
36          public final String getName() {
37              return name;
38          }
39  
40          /**
41           * Base method.
42           *
43           * @param i
44           *            the i
45           *
46           * @return the int
47           */
48          public final int baseMethod(int i) {
49              return i + 1;
50          }
51  
52          /**
53           * Method to be mocked.
54           *
55           * @param i
56           *            the i
57           *
58           * @return the int
59           *
60           * @throws IOException
61           *             Signals that an I/O exception has occurred.
62           */
63          protected int methodToBeMocked(int i) throws IOException {
64              return i;
65          }
66      }
67  
68      /**
69       * The Class ClassToBeMocked.
70       */
71      public static class ClassToBeMocked extends BaseClassToBeMocked {
72  
73          /**
74           * Instantiates a new class to be mocked.
75           */
76          public ClassToBeMocked() {
77              name = "";
78          }
79  
80          /**
81           * Instantiates a new class to be mocked.
82           *
83           * @param name
84           *            the name
85           */
86          public ClassToBeMocked(String name) {
87              this.name = name;
88          }
89  
90          /**
91           * Method to be mocked.
92           *
93           * @return true, if successful
94           */
95          public boolean methodToBeMocked() {
96              return true;
97          }
98  
99          @Override
100         protected int methodToBeMocked(int i) throws IOException {
101             return super.methodToBeMocked(i);
102         }
103 
104         /**
105          * Method to be mocked.
106          *
107          * @param i
108          *            the i
109          * @param args
110          *            the args
111          *
112          * @return the int
113          */
114         int methodToBeMocked(int i, Object... args) {
115             int result = i;
116 
117             for (Object arg : args) {
118                 if (arg != null) {
119                     result++;
120                 }
121             }
122 
123             return result;
124         }
125 
126         /**
127          * Another method to be mocked.
128          *
129          * @param s
130          *            the s
131          * @param b
132          *            the b
133          * @param ints
134          *            the ints
135          *
136          * @return the string
137          */
138         String anotherMethodToBeMocked(String s, boolean b, List<Integer> ints) {
139             return (b ? s.toUpperCase() : s.toLowerCase()) + ints;
140         }
141     }
142 
143     /**
144      * Proceed from delegate method on regular mocked class.
145      *
146      * @param mocked
147      *            the mocked
148      */
149     @Test
150     void proceedFromDelegateMethodOnRegularMockedClass(@Mocked final ClassToBeMocked mocked) {
151         new Expectations() {
152             {
153                 mocked.methodToBeMocked();
154                 result = new Delegate<Object>() {
155                     @Mock
156                     boolean delegate(Invocation inv) {
157                         return inv.proceed();
158                     }
159                 };
160             }
161         };
162 
163         assertTrue(mocked.methodToBeMocked());
164     }
165 
166     /**
167      * Proceed from delegate method on injectable mocked class.
168      *
169      * @param mocked
170      *            the mocked
171      */
172     @Test
173     void proceedFromDelegateMethodOnInjectableMockedClass(@Injectable final ClassToBeMocked mocked) {
174         new Expectations() {
175             {
176                 mocked.methodToBeMocked();
177                 result = new Delegate<Object>() {
178                     @Mock
179                     boolean delegate(Invocation inv) {
180                         return inv.proceed();
181                     }
182                 };
183             }
184         };
185 
186         assertTrue(mocked.methodToBeMocked());
187     }
188 
189     /**
190      * Proceed from delegate method with parameters.
191      *
192      * @throws Exception
193      *             the exception
194      */
195     @Test
196     void proceedFromDelegateMethodWithParameters() throws Exception {
197         final ClassToBeMocked mocked = new ClassToBeMocked();
198 
199         new Expectations(mocked) {
200             {
201                 mocked.methodToBeMocked(anyInt);
202                 result = new Delegate<Object>() {
203                     @Mock
204                     int delegate(Invocation inv, int i) {
205                         Integer j = inv.proceed();
206                         return j + 1;
207                     }
208                 };
209 
210                 mocked.methodToBeMocked(anyInt, (Object[]) any);
211                 maxTimes = 1;
212                 result = new Delegate<Object>() {
213                     @Mock
214                     Integer delegate(Invocation inv, int i, Object... args) {
215                         args[2] = "mock";
216                         return inv.proceed();
217                     }
218                 };
219             }
220         };
221 
222         assertEquals(124, mocked.methodToBeMocked(123));
223         assertEquals(-8, mocked.methodToBeMocked(-9));
224         assertEquals(7, mocked.methodToBeMocked(3, "Test", new Object(), null, 45));
225     }
226 
227     /**
228      * Proceed conditionally from delegate method.
229      */
230     @Test
231     void proceedConditionallyFromDelegateMethod() {
232         final ClassToBeMocked mocked = new ClassToBeMocked();
233 
234         new Expectations(mocked) {
235             {
236                 mocked.anotherMethodToBeMocked(anyString, anyBoolean, null);
237                 result = new Delegate<Object>() {
238                     @Mock
239                     String delegate(Invocation inv, String s, boolean b, List<Number> ints) {
240                         if (!b) {
241                             return s;
242                         }
243 
244                         ints.add(45);
245                         return inv.proceed();
246                     }
247                 };
248             }
249         };
250 
251         // Do not proceed:
252         assertNull(mocked.anotherMethodToBeMocked(null, false, null));
253 
254         // Do proceed:
255         List<Integer> values = new ArrayList<>();
256         assertEquals("TEST[45]", mocked.anotherMethodToBeMocked("test", true, values));
257 
258         // Do not proceed again:
259         assertEquals("No proceed", mocked.anotherMethodToBeMocked("No proceed", false, null));
260     }
261 
262     /**
263      * Proceed from delegate method into real method with modified arguments.
264      *
265      * @throws Exception
266      *             the exception
267      */
268     @Test
269     void proceedFromDelegateMethodIntoRealMethodWithModifiedArguments() throws Exception {
270         final ClassToBeMocked mocked = new ClassToBeMocked();
271 
272         new Expectations(mocked) {
273             {
274                 mocked.methodToBeMocked(anyInt);
275                 result = new Delegate<Object>() {
276                     @Mock
277                     Integer delegate1(Invocation invocation, int i) {
278                         return invocation.proceed(i + 2);
279                     }
280                 };
281 
282                 mocked.methodToBeMocked(anyInt, (Object[]) any);
283                 result = new Delegate<Object>() {
284                     @Mock
285                     Integer delegate2(Invocation inv, int i, Object... args) {
286                         Object[] newArgs = { 2, "3" };
287                         return inv.proceed(1, newArgs);
288                     }
289                 };
290             }
291         };
292 
293         assertEquals(3, mocked.methodToBeMocked(1));
294         assertEquals(3, mocked.methodToBeMocked(-2, null, "Abc", true, 'a'));
295     }
296 
297     /**
298      * Proceed from delegate method into constructor.
299      *
300      * @param mock
301      *            the mock
302      */
303     @Test
304     void proceedFromDelegateMethodIntoConstructor(@Mocked ClassToBeMocked mock) {
305         new Expectations() {
306             {
307                 new ClassToBeMocked();
308                 result = new Delegate<Object>() {
309                     @Mock
310                     void init(Invocation inv) {
311                         assertNotNull(inv.getInvokedInstance());
312                         inv.proceed();
313                     }
314                 };
315             }
316         };
317 
318         ClassToBeMocked obj = new ClassToBeMocked();
319         assertEquals("", obj.name);
320     }
321 
322     /**
323      * Proceed conditionally from delegate method into constructor.
324      *
325      * @param mock
326      *            the mock
327      */
328     @Test
329     void proceedConditionallyFromDelegateMethodIntoConstructor(@Mocked ClassToBeMocked mock) {
330         new Expectations() {
331             {
332                 new ClassToBeMocked(anyString);
333                 result = new Delegate<Object>() {
334                     @Mock
335                     void init(Invocation inv, String name) {
336                         assertNotNull(inv.getInvokedInstance());
337 
338                         if ("proceed".equals(name)) {
339                             inv.proceed();
340                         }
341                     }
342                 };
343             }
344         };
345 
346         assertEquals("proceed", new ClassToBeMocked("proceed").name);
347         assertNull(new ClassToBeMocked("do not proceed").name);
348     }
349 
350     /**
351      * Proceed from delegate method into JRE constructor.
352      *
353      * @param mock
354      *            the mock
355      */
356     @Test
357     void proceedFromDelegateMethodIntoJREConstructor(@Mocked ProcessBuilder mock) {
358         new Expectations() {
359             {
360                 ProcessBuilder pb = new ProcessBuilder((String[]) any);
361                 result = new Delegate<Object>() {
362                     @Mock
363                     void init(Invocation inv) {
364                         inv.proceed();
365                     }
366                 };
367 
368                 pb.command();
369                 result = new Delegate<Object>() {
370                     @Mock
371                     List<String> delegate(Invocation inv) {
372                         return inv.proceed();
373                     }
374                 };
375             }
376         };
377 
378         ProcessBuilder pb1 = new ProcessBuilder("proceed");
379         assertEquals("proceed", pb1.command().get(0));
380 
381         ProcessBuilder pb2 = new ProcessBuilder("proceed", "again");
382         assertEquals(asList("proceed", "again"), pb2.command());
383     }
384 
385     /**
386      * Proceed from delegate method into method inherited from base class.
387      */
388     @Test
389     void proceedFromDelegateMethodIntoMethodInheritedFromBaseClass() {
390         final ClassToBeMocked obj = new ClassToBeMocked();
391 
392         new Expectations(obj) {
393             {
394                 obj.baseMethod(anyInt);
395                 result = new Delegate<Object>() {
396                     @Mock
397                     int baseMethod(Invocation inv, int i) {
398                         return inv.proceed(i + 1);
399                     }
400                 };
401             }
402         };
403 
404         assertEquals(3, obj.baseMethod(1));
405     }
406 
407     /**
408      * Proceed from delegate method into overriding method which calls super.
409      *
410      * @param mocked
411      *            the mocked
412      *
413      * @throws Exception
414      *             the exception
415      */
416     @Test
417     void proceedFromDelegateMethodIntoOverridingMethodWhichCallsSuper(@Mocked final ClassToBeMocked mocked)
418             throws Exception {
419         new Expectations() {
420             {
421                 mocked.methodToBeMocked(1);
422                 result = new Delegate<Object>() {
423                     @Mock
424                     int delegate(Invocation inv) {
425                         return inv.proceed();
426                     }
427                 };
428             }
429         };
430 
431         assertEquals(1, mocked.methodToBeMocked(1));
432     }
433 
434     /**
435      * Proceed from delegate method into overriding method that calls super which also has A proceeding delegate.
436      *
437      * @param mockedBase
438      *            the mocked base
439      * @param mocked
440      *            the mocked
441      *
442      * @throws Exception
443      *             the exception
444      */
445     @Test
446     void proceedFromDelegateMethodIntoOverridingMethodThatCallsSuperWhichAlsoHasAProceedingDelegate(
447             @Mocked final BaseClassToBeMocked mockedBase, @Mocked final ClassToBeMocked mocked) throws Exception {
448         new Expectations() {
449             {
450                 mockedBase.methodToBeMocked(1);
451                 result = new Delegate<Object>() {
452                     // Will not execute when calling on subclass instance.
453                     @Mock
454                     int delegate(Invocation inv) {
455                         int i = inv.proceed();
456                         return i + 1;
457                     }
458                 };
459 
460                 mocked.methodToBeMocked(1);
461                 result = new Delegate<Object>() {
462                     @Mock
463                     int delegate(Invocation inv) {
464                         return inv.proceed();
465                     }
466                 };
467             }
468         };
469 
470         assertEquals(2, mockedBase.methodToBeMocked(1));
471         assertEquals(1, mocked.methodToBeMocked(1));
472     }
473 
474     /**
475      * Throw exception from proceed into JRE method.
476      *
477      * @param c1
478      *            the c 1
479      * @param c2
480      *            the c 2
481      *
482      * @throws Exception
483      *             the exception
484      */
485     @Test
486     void throwExceptionFromProceedIntoJREMethod(@Injectable final AbstractExecutorService c1,
487             @Mocked final ClassToBeMocked c2) throws Exception {
488         new Expectations() {
489             {
490                 c1.submit((Runnable) any);
491                 result = new Delegate<Object>() {
492                     @Mock
493                     void delegate(Invocation inv) {
494                         inv.proceed();
495                     }
496                 };
497             }
498         };
499 
500         try {
501             c1.submit((Runnable) null);
502             fail();
503         } catch (NullPointerException ignored) {
504             new Expectations() {
505                 {
506                     c2.methodToBeMocked(anyInt);
507                     result = 123;
508                 }
509             };
510 
511             assertEquals(123, c2.methodToBeMocked(1));
512         }
513     }
514 }