View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertNotNull;
5   import static org.junit.jupiter.api.Assertions.assertNull;
6   import static org.junit.jupiter.api.Assertions.assertThrows;
7   import static org.junit.jupiter.api.Assertions.assertTrue;
8   import static org.junit.jupiter.api.Assertions.fail;
9   
10  import java.io.File;
11  import java.io.FileNotFoundException;
12  import java.nio.file.Path;
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  import org.junit.jupiter.api.Test;
17  
18  /**
19   * The Class FakeInvocationProceedTest.
20   */
21  public final class FakeInvocationProceedTest {
22  
23      /**
24       * The Class BaseClassToBeFaked.
25       */
26      public static class BaseClassToBeFaked {
27  
28          /** The name. */
29          protected String name;
30  
31          /**
32           * Base method.
33           *
34           * @param i
35           *            the i
36           *
37           * @return the int
38           */
39          public final int baseMethod(int i) {
40              return i + 1;
41          }
42  
43          /**
44           * Method to be faked.
45           *
46           * @param i
47           *            the i
48           *
49           * @return the int
50           */
51          protected int methodToBeFaked(int i) {
52              return i;
53          }
54      }
55  
56      /**
57       * The Class ClassToBeFaked.
58       */
59      public static class ClassToBeFaked extends BaseClassToBeFaked {
60  
61          /**
62           * Instantiates a new class to be faked.
63           */
64          public ClassToBeFaked() {
65              name = "";
66          }
67  
68          /**
69           * Instantiates a new class to be faked.
70           *
71           * @param name
72           *            the name
73           */
74          public ClassToBeFaked(String name) {
75              this.name = name;
76          }
77  
78          /**
79           * Method to be faked.
80           *
81           * @return true, if successful
82           */
83          public boolean methodToBeFaked() {
84              return true;
85          }
86  
87          /**
88           * Method to be faked.
89           *
90           * @param i
91           *            the i
92           * @param args
93           *            the args
94           *
95           * @return the int
96           */
97          protected int methodToBeFaked(int i, Object... args) {
98              int result = i;
99  
100             for (Object arg : args) {
101                 if (arg != null) {
102                     result++;
103                 }
104             }
105 
106             return result;
107         }
108 
109         /**
110          * Another method to be faked.
111          *
112          * @param s
113          *            the s
114          * @param b
115          *            the b
116          * @param ints
117          *            the ints
118          *
119          * @return the string
120          */
121         public String anotherMethodToBeFaked(String s, boolean b, List<Integer> ints) {
122             return (b ? s.toUpperCase() : s.toLowerCase()) + ints;
123         }
124 
125         /**
126          * Static method to be faked.
127          *
128          * @return true, if successful
129          *
130          * @throws FileNotFoundException
131          *             the file not found exception
132          */
133         public static boolean staticMethodToBeFaked() throws FileNotFoundException {
134             throw new FileNotFoundException();
135         }
136 
137         /**
138          * Native method.
139          */
140         protected static native void nativeMethod();
141     }
142 
143     /**
144      * Proceed from fake method without parameters.
145      */
146     @Test
147     public void proceedFromFakeMethodWithoutParameters() {
148         new MockUp<ClassToBeFaked>() {
149             @Mock
150             boolean methodToBeMocked(Invocation inv) {
151                 return inv.proceed();
152             }
153         };
154 
155         assertTrue(new ClassToBeFaked().methodToBeFaked());
156     }
157 
158     /**
159      * Proceed from fake method with parameters.
160      */
161     @Test
162     public void proceedFromFakeMethodWithParameters() {
163         new MockUp<ClassToBeFaked>() {
164             @Mock
165             int methodToBeFaked(Invocation inv, int i) {
166                 Integer j = inv.proceed();
167                 return j + 1;
168             }
169 
170             @Mock
171             private int methodToBeFaked(Invocation inv, int i, Object... args) {
172                 args[2] = "mock";
173                 return inv.<Integer> proceed();
174             }
175         };
176 
177         ClassToBeFaked faked = new ClassToBeFaked();
178 
179         assertEquals(124, faked.methodToBeFaked(123));
180         assertEquals(-8, faked.methodToBeFaked(-9));
181         assertEquals(7, faked.methodToBeFaked(3, "Test", new Object(), null, 45));
182     }
183 
184     /**
185      * Proceed conditionally from fake method.
186      */
187     @Test
188     public void proceedConditionallyFromFakeMethod() {
189         new MockUp<ClassToBeFaked>() {
190             @Mock
191             String anotherMethodToBeFaked(Invocation inv, String s, boolean b, List<Number> ints) {
192                 if (!b) {
193                     return s;
194                 }
195 
196                 ints.add(45);
197                 return inv.proceed();
198             }
199         };
200 
201         ClassToBeFaked mocked = new ClassToBeFaked();
202 
203         // Do not proceed:
204         assertNull(mocked.anotherMethodToBeFaked(null, false, null));
205 
206         // Do proceed:
207         List<Integer> values = new ArrayList<>();
208         assertEquals("TEST[45]", mocked.anotherMethodToBeFaked("test", true, values));
209 
210         // Do not proceed again:
211         assertEquals("No proceed", mocked.anotherMethodToBeFaked("No proceed", false, null));
212     }
213 
214     /**
215      * Proceed from fake method which throws checked exception.
216      *
217      * @throws Exception
218      *             the exception
219      */
220     @Test
221     public void proceedFromFakeMethodWhichThrowsCheckedException() throws Exception {
222         new MockUp<ClassToBeFaked>() {
223             @Mock
224             boolean staticMethodToBeFaked(Invocation inv) throws Exception {
225                 if (inv.getInvocationIndex() == 0) {
226                     return inv.<Boolean> proceed();
227                 }
228 
229                 throw new InterruptedException("fake");
230             }
231         };
232 
233         try {
234             ClassToBeFaked.staticMethodToBeFaked();
235             fail();
236         } catch (FileNotFoundException ignored) {
237         }
238 
239         assertThrows(InterruptedException.class, () -> {
240             ClassToBeFaked.staticMethodToBeFaked();
241         });
242     }
243 
244     /**
245      * Proceed from fake method into real method with modified arguments.
246      */
247     @Test
248     public void proceedFromFakeMethodIntoRealMethodWithModifiedArguments() {
249         class FakeWhichModifiesArguments extends MockUp<ClassToBeFaked> {
250             @Mock
251             final int methodToBeFaked(Invocation invocation, int i) {
252                 return invocation.<Integer> proceed(i + 2);
253             }
254         }
255 
256         new FakeWhichModifiesArguments() {
257             @Mock
258             synchronized int methodToBeFaked(Invocation inv, int i, Object... args) {
259                 Object[] newArgs = { 2, "3" };
260                 return inv.<Integer> proceed(1, newArgs);
261             }
262         };
263 
264         ClassToBeFaked faked = new ClassToBeFaked();
265         assertEquals(3, faked.methodToBeFaked(1));
266         assertEquals(3, faked.methodToBeFaked(-2, null, "Abc", true, 'a'));
267     }
268 
269     /**
270      * Cannot proceed from fake method into native method.
271      */
272     @Test
273     public void cannotProceedFromFakeMethodIntoNativeMethod() {
274         new MockUp<ClassToBeFaked>() {
275             @Mock
276             void nativeMethod(Invocation inv) {
277                 inv.proceed();
278                 fail("Should not get here");
279             }
280         };
281 
282         Throwable throwable = assertThrows(UnsupportedOperationException.class, () -> {
283             ClassToBeFaked.nativeMethod();
284         });
285         assertEquals("Cannot proceed into real implementation of native method", throwable.getMessage());
286     }
287 
288     /**
289      * Proceed from fake method into constructor.
290      */
291     @Test
292     public void proceedFromFakeMethodIntoConstructor() {
293         new MockUp<ClassToBeFaked>() {
294             @Mock
295             void $init(Invocation inv) {
296                 assertNotNull(inv.<ClassToBeFaked> getInvokedInstance());
297                 inv.proceed();
298             }
299         };
300 
301         ClassToBeFaked obj = new ClassToBeFaked();
302         assertEquals("", obj.name);
303     }
304 
305     /**
306      * Proceed conditionally from fake method into constructor.
307      */
308     @Test
309     public void proceedConditionallyFromFakeMethodIntoConstructor() {
310         new MockUp<ClassToBeFaked>() {
311             @Mock
312             void $init(Invocation inv, String name) {
313                 assertNotNull(inv.getInvokedInstance());
314 
315                 if ("proceed".equals(name)) {
316                     inv.proceed();
317                 }
318             }
319         };
320 
321         assertEquals("proceed", new ClassToBeFaked("proceed").name);
322         assertNull(new ClassToBeFaked("do not proceed").name);
323     }
324 
325     /**
326      * Proceed conditionally from fake method into JRE constructor.
327      */
328     @Test
329     public void proceedConditionallyFromFakeMethodIntoJREConstructor() {
330         new MockUp<File>() {
331             @Mock
332             void $init(Invocation inv, String name) {
333                 if ("proceed".equals(name)) {
334                     inv.proceed();
335                 }
336             }
337         };
338 
339         assertEquals("proceed", Path.of("proceed").toFile().toString());
340         assertNull(Path.of("do not proceed").toFile().toString());
341     }
342 
343     /**
344      * Proceed from fake method into method inherited from base class.
345      */
346     @Test
347     public void proceedFromFakeMethodIntoMethodInheritedFromBaseClass() {
348         new MockUp<ClassToBeFaked>() {
349             @Mock
350             int baseMethod(Invocation inv, int i) {
351                 return inv.proceed(i + 1);
352             }
353         };
354 
355         assertEquals(3, new ClassToBeFaked().baseMethod(1));
356     }
357 }