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.assertThrows;
12  import static org.junit.jupiter.api.Assertions.assertTrue;
13  import static org.junit.jupiter.api.Assertions.fail;
14  
15  import java.io.File;
16  import java.io.FileNotFoundException;
17  import java.io.IOException;
18  import java.nio.file.Path;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.junit.jupiter.api.Test;
23  
24  public final class MockInvocationProceedTest {
25  
26      public static class BaseClassToBeMocked {
27          protected String name;
28  
29          public final int baseMethod(int i) {
30              return i + 1;
31          }
32  
33          protected int methodToBeMocked(int i) throws IOException {
34              return i;
35          }
36      }
37  
38      public static class ClassToBeMocked extends BaseClassToBeMocked {
39          public ClassToBeMocked() {
40              name = "";
41          }
42  
43          public ClassToBeMocked(String name) {
44              this.name = name;
45          }
46  
47          public boolean methodToBeMocked() {
48              return true;
49          }
50  
51          protected int methodToBeMocked(int i, Object... args) {
52              int result = i;
53  
54              for (Object arg : args) {
55                  if (arg != null)
56                      result++;
57              }
58  
59              return result;
60          }
61  
62          public String anotherMethodToBeMocked(String s, boolean b, List<Integer> ints) {
63              return (b ? s.toUpperCase() : s.toLowerCase()) + ints;
64          }
65  
66          public static boolean staticMethodToBeMocked() throws FileNotFoundException {
67              throw new FileNotFoundException();
68          }
69  
70          protected static native void nativeMethod();
71      }
72  
73      @Test
74      public void proceedFromMockMethodWithoutParameters() {
75          new MockUp<ClassToBeMocked>() {
76              @Mock
77              boolean methodToBeMocked(Invocation inv) {
78                  return inv.proceed();
79              }
80          };
81  
82          assertTrue(new ClassToBeMocked().methodToBeMocked());
83      }
84  
85      @Test
86      public void proceedFromMockMethodWithParameters() throws Exception {
87          new MockUp<ClassToBeMocked>() {
88              @Mock
89              int methodToBeMocked(Invocation inv, int i) {
90                  Integer j = inv.proceed();
91                  return j + 1;
92              }
93  
94              @Mock
95              private int methodToBeMocked(Invocation inv, int i, Object... args) {
96                  args[2] = "mock";
97                  return inv.<Integer> proceed();
98              }
99          };
100 
101         ClassToBeMocked mocked = new ClassToBeMocked();
102 
103         assertEquals(124, mocked.methodToBeMocked(123));
104         assertEquals(-8, mocked.methodToBeMocked(-9));
105         assertEquals(7, mocked.methodToBeMocked(3, "Test", new Object(), null, 45));
106     }
107 
108     @Test
109     public void proceedConditionallyFromMockMethod() throws Exception {
110         new MockUp<ClassToBeMocked>() {
111             @Mock
112             String anotherMethodToBeMocked(Invocation inv, String s, boolean b, List<Number> ints) {
113                 if (!b) {
114                     return s;
115                 }
116 
117                 ints.add(45);
118                 return inv.proceed();
119             }
120         };
121 
122         ClassToBeMocked mocked = new ClassToBeMocked();
123 
124         // Do not proceed:
125         assertNull(mocked.anotherMethodToBeMocked(null, false, null));
126 
127         // Do proceed:
128         List<Integer> values = new ArrayList<>();
129         assertEquals("TEST[45]", mocked.anotherMethodToBeMocked("test", true, values));
130 
131         // Do not proceed again:
132         assertEquals("No proceed", mocked.anotherMethodToBeMocked("No proceed", false, null));
133     }
134 
135     @Test
136     public void proceedFromMockMethodWhichThrowsCheckedException() throws Exception {
137         new MockUp<ClassToBeMocked>() {
138             @Mock
139             boolean staticMethodToBeMocked(Invocation inv) throws Exception {
140                 if (inv.getInvocationIndex() == 0) {
141                     return inv.<Boolean> proceed();
142                 }
143 
144                 throw new InterruptedException("fake");
145             }
146         };
147 
148         try {
149             ClassToBeMocked.staticMethodToBeMocked();
150             fail();
151         } catch (FileNotFoundException ignored) {
152         }
153 
154         assertThrows(InterruptedException.class, () -> {
155             ClassToBeMocked.staticMethodToBeMocked();
156         });
157     }
158 
159     @Test
160     public void cannotProceedFromMockMethodIntoNativeMethod() {
161         new MockUp<ClassToBeMocked>() {
162             @Mock
163             void nativeMethod(Invocation inv) {
164                 inv.proceed();
165                 fail("Should not get here");
166             }
167         };
168 
169         Throwable throwable = assertThrows(UnsupportedOperationException.class, () -> {
170             ClassToBeMocked.nativeMethod();
171         });
172         assertEquals("Cannot proceed into real implementation of native method", throwable.getMessage());
173     }
174 
175     @Test
176     public void proceedFromMockMethodIntoConstructor() {
177         new MockUp<ClassToBeMocked>() {
178             @Mock
179             void $init(Invocation inv) {
180                 assertNotNull(inv.<ClassToBeMocked> getInvokedInstance());
181                 inv.proceed();
182             }
183         };
184 
185         ClassToBeMocked obj = new ClassToBeMocked();
186         assertEquals("", obj.name);
187     }
188 
189     @Test
190     public void proceedConditionallyFromMockMethodIntoConstructor() {
191         new MockUp<ClassToBeMocked>() {
192             @Mock
193             void $init(Invocation inv, String name) {
194                 assertNotNull(inv.getInvokedInstance());
195 
196                 if ("proceed".equals(name)) {
197                     inv.proceed();
198                 }
199             }
200         };
201 
202         assertEquals("proceed", new ClassToBeMocked("proceed").name);
203         assertNull(new ClassToBeMocked("do not proceed").name);
204     }
205 
206     @Test
207     public void proceedConditionallyFromMockMethodIntoJREConstructor() {
208         new MockUp<File>() {
209             @Mock
210             void $init(Invocation inv, String name) {
211                 if ("proceed".equals(name)) {
212                     inv.proceed();
213                 }
214             }
215         };
216 
217         assertEquals("proceed", Path.of("proceed").toFile().toString());
218         assertNull(Path.of("do not proceed").toFile().toString());
219     }
220 
221     @Test
222     public void proceedFromMockMethodIntoMethodInheritedFromBaseClass() {
223         new MockUp<ClassToBeMocked>() {
224             @Mock
225             int baseMethod(Invocation inv, int i) {
226                 return inv.proceed(i + 1);
227             }
228         };
229 
230         assertEquals(3, new ClassToBeMocked().baseMethod(1));
231     }
232 }