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 org.junit.jupiter.api.Assertions.assertEquals;
9   import static org.junit.jupiter.api.Assertions.assertNotNull;
10  import static org.junit.jupiter.api.Assertions.assertNull;
11  import static org.junit.jupiter.api.Assertions.assertSame;
12  import static org.junit.jupiter.api.Assertions.assertTrue;
13  import static org.junit.jupiter.api.Assertions.fail;
14  
15  import java.util.concurrent.Callable;
16  
17  import mockit.integration.junit5.JMockitExtension;
18  
19  import org.junit.jupiter.api.Test;
20  import org.junit.jupiter.api.extension.ExtendWith;
21  
22  /**
23   * The Class DelegateInvocationTest.
24   */
25  @ExtendWith(JMockitExtension.class)
26  class DelegateInvocationTest {
27  
28      /**
29       * The Class Collaborator.
30       */
31      static class Collaborator {
32  
33          /**
34           * Instantiates a new collaborator.
35           */
36          Collaborator() {
37          }
38  
39          /**
40           * Instantiates a new collaborator.
41           *
42           * @param i
43           *            the i
44           */
45          Collaborator(@SuppressWarnings("unused") int i) {
46          }
47  
48          /**
49           * Gets the value.
50           *
51           * @return the value
52           */
53          int getValue() {
54              return -1;
55          }
56  
57          /**
58           * Do something.
59           *
60           * @param b
61           *            the b
62           * @param i
63           *            the i
64           * @param s
65           *            the s
66           *
67           * @return the string
68           */
69          String doSomething(boolean b, int[] i, String s) {
70              return s + b + i[0];
71          }
72  
73          /**
74           * Static method.
75           *
76           * @return true, if successful
77           */
78          static boolean staticMethod() {
79              return true;
80          }
81  
82          /**
83           * Static method.
84           *
85           * @param i
86           *            the i
87           *
88           * @return true, if successful
89           */
90          static boolean staticMethod(int i) {
91              return i > 0;
92          }
93  
94          /**
95           * Public method.
96           *
97           * @param b
98           *            the b
99           *
100          * @return the long
101          */
102         public long publicMethod(boolean b) {
103             return b ? 0L : -1L;
104         }
105     }
106 
107     /**
108      * Delegate with context object.
109      *
110      * @param unused
111      *            the unused
112      */
113     @Test
114     void delegateWithContextObject(@Mocked Collaborator unused) {
115         new Expectations() {
116             {
117                 Collaborator.staticMethod();
118                 result = new Delegate<Object>() {
119                     @Mock
120                     boolean staticMethod(Invocation context) {
121                         assertNull(context.getInvokedInstance());
122                         assertEquals(0, context.getInvokedArguments().length);
123                         assertEquals(context.getInvocationCount() - 1, context.getInvocationIndex());
124                         return context.getInvocationCount() > 0;
125                     }
126                 };
127             }
128         };
129 
130         assertTrue(Collaborator.staticMethod());
131         assertTrue(Collaborator.staticMethod());
132     }
133 
134     /**
135      * The Class ConstructorDelegate.
136      */
137     static class ConstructorDelegate implements Delegate<Void> {
138 
139         /** The captured argument. */
140         int capturedArgument;
141 
142         /**
143          * Inits the.
144          *
145          * @param context
146          *            the context
147          * @param i
148          *            the i
149          */
150         @Mock
151         void init(Invocation context, int i) {
152             assertNotNull(context.getInvokedInstance());
153             capturedArgument = i + context.getInvocationCount();
154         }
155     }
156 
157     /**
158      * Delegate for constructor with context.
159      *
160      * @param mock
161      *            the mock
162      */
163     @Test
164     void delegateForConstructorWithContext(@Mocked Collaborator mock) {
165         final ConstructorDelegate delegate = new ConstructorDelegate();
166 
167         new Expectations() {
168             {
169                 new Collaborator(anyInt);
170                 result = delegate;
171             }
172         };
173 
174         new Collaborator(4);
175 
176         assertEquals(5, delegate.capturedArgument);
177     }
178 
179     /**
180      * Delegate receiving null arguments.
181      *
182      * @param mock
183      *            the mock
184      */
185     @Test
186     void delegateReceivingNullArguments(@Mocked final Collaborator mock) {
187         new Expectations() {
188             {
189                 mock.doSomething(true, null, null);
190                 result = new Delegate<Object>() {
191                     @Mock
192                     void doSomething(Invocation invocation, Boolean b, int[] i, String s) {
193                         Collaborator instance = invocation.getInvokedInstance();
194                         assertSame(mock, instance);
195                         assertEquals(1, invocation.getInvocationCount());
196                         assertTrue(b);
197                         assertNull(i);
198                         assertNull(s);
199                         Object[] args = invocation.getInvokedArguments();
200                         assertEquals(3, args.length);
201                         assertTrue((Boolean) args[0]);
202                         assertNull(args[1]);
203                         assertNull(args[2]);
204                     }
205                 };
206             }
207         };
208 
209         assertNull(mock.doSomething(true, null, null));
210     }
211 
212     /**
213      * Delegate with another method on the delegate class.
214      *
215      * @param mock
216      *            the mock
217      */
218     @Test
219     void delegateWithAnotherMethodOnTheDelegateClass(@Mocked final Collaborator mock) {
220         new Expectations() {
221             {
222                 mock.getValue();
223                 result = new Delegate<Object>() {
224                     @Mock
225                     int getValue(Invocation context) {
226                         return context.getInvocationCount();
227                     }
228 
229                     @SuppressWarnings("unused")
230                     private void otherMethod(Invocation context) {
231                         fail();
232                     }
233                 };
234             }
235         };
236 
237         assertEquals(1, new Collaborator().getValue());
238         assertEquals(2, new Collaborator().getValue());
239     }
240 
241     /**
242      * Delegate class with multiple methods and inexact but valid match.
243      *
244      * @param mock
245      *            the mock
246      */
247     @Test
248     void delegateClassWithMultipleMethodsAndInexactButValidMatch(@Mocked Collaborator mock) {
249         new Expectations() {
250             {
251                 Collaborator.staticMethod(1);
252                 result = new Delegate<Object>() {
253                     @SuppressWarnings("unused")
254                     private void otherMethod(int i) {
255                         fail();
256                     }
257 
258                     @Mock
259                     boolean staticMethod(Invocation invocation, Number i) {
260                         return i.intValue() > 0;
261                     }
262                 };
263             }
264         };
265 
266         assertTrue(Collaborator.staticMethod(1));
267     }
268 
269     /**
270      * Delegate method with no parameters for expectation with parameters.
271      *
272      * @param mock
273      *            the mock
274      */
275     @Test
276     void delegateMethodWithNoParametersForExpectationWithParameters(@Mocked final Collaborator mock) {
277         new Expectations() {
278             {
279                 mock.publicMethod(true);
280                 result = new Delegate<Object>() {
281                     @Mock
282                     long nonMatchingDelegate() {
283                         return 123L;
284                     }
285                 };
286             }
287         };
288 
289         assertEquals(123, mock.publicMethod(true));
290     }
291 
292     /**
293      * Delegate with different method name.
294      *
295      * @param mock
296      *            the mock
297      */
298     @Test
299     void delegateWithDifferentMethodName(@Mocked final Collaborator mock) {
300         new Expectations() {
301             {
302                 mock.publicMethod(anyBoolean);
303                 result = new Delegate<Object>() {
304                     @Mock
305                     long differentName(Invocation invocation, boolean b) {
306                         assertEquals(1, invocation.getInvocationCount());
307                         assertTrue(b);
308                         assertSame(Boolean.TRUE, invocation.getInvokedArguments()[0]);
309                         return 3L;
310                     }
311                 };
312             }
313         };
314 
315         assertEquals(3L, new Collaborator().publicMethod(true));
316     }
317 
318     /**
319      * Consecutive delegates for the same expectation.
320      *
321      * @param mock
322      *            the mock
323      */
324     @Test
325     void consecutiveDelegatesForTheSameExpectation(@Mocked final Collaborator mock) {
326         new Expectations() {
327             {
328                 mock.getValue();
329                 returns(new Delegate<Object>() {
330                     @Mock
331                     int delegate(Invocation invocation) {
332                         assertSame(mock, invocation.getInvokedInstance());
333                         return invocation.getInvocationCount();
334                     }
335                 }, new Delegate<Object>() {
336                     @Mock
337                     int delegate(Invocation invocation) {
338                         return invocation.getInvocationCount();
339                     }
340                 }, new Delegate<Object>() {
341                     @Mock
342                     int delegate(Invocation invocation) {
343                         assertEquals(3, invocation.getInvocationCount());
344                         throw new SecurityException();
345                     }
346                 });
347             }
348         };
349 
350         assertEquals(1, mock.getValue());
351         assertEquals(2, mock.getValue());
352 
353         try {
354             mock.getValue();
355             fail();
356         } catch (SecurityException ignore) {
357             // OK
358         }
359     }
360 
361     /**
362      * Delegate method with invocation for interface.
363      *
364      * @param mock
365      *            the mock
366      *
367      * @throws Exception
368      *             the exception
369      */
370     @Test
371     void delegateMethodWithInvocationForInterface(@Mocked final Callable<String> mock) throws Exception {
372         new Expectations() {
373             {
374                 mock.call();
375                 result = new Delegate<Object>() {
376                     @Mock
377                     String delegate(Invocation inv) {
378                         return inv.getInvokedMember().getDeclaringClass().getName();
379                     }
380                 };
381             }
382         };
383 
384         String s = mock.call();
385 
386         assertEquals(Callable.class.getName(), s);
387     }
388 
389     /**
390      * Use of context parameters for JRE methods.
391      *
392      * @throws Exception
393      *             the exception
394      */
395     @Test
396     void useOfContextParametersForJREMethods() throws Exception {
397         final Runtime rt = Runtime.getRuntime();
398 
399         new Expectations(rt) {
400             {
401                 rt.exec(anyString, null);
402                 maxTimes = 1;
403                 result = new Delegate<Object>() {
404                     @Mock
405                     void exec(Invocation inv, String command, String[] envp) {
406                         assertSame(rt, inv.getInvokedInstance());
407                         assertEquals(0, inv.getInvocationIndex());
408                         assertNotNull(command);
409                         assertNull(envp);
410                     }
411                 };
412             }
413         };
414 
415         assertNull(rt.exec("test", null));
416     }
417 }