View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertSame;
5   
6   import edu.umd.cs.findbugs.annotations.NonNull;
7   
8   import java.io.Writer;
9   
10  import org.junit.jupiter.api.Test;
11  
12  /**
13   * The Class MockedClassWithSuperClassTest.
14   */
15  final class MockedClassWithSuperClassTest {
16  
17      /**
18       * The Class SubclassOfJREClass.
19       */
20      static class SubclassOfJREClass extends Writer {
21          @Override
22          public void write(@NonNull char[] cbuf, int off, int len) {
23          }
24  
25          @Override
26          public void flush() {
27          }
28  
29          @Override
30          public void close() {
31              throw new UnsupportedOperationException();
32          }
33      }
34  
35      /**
36       * The Class BaseClass.
37       */
38      static class BaseClass {
39  
40          /**
41           * Do something.
42           *
43           * @return the int
44           */
45          protected int doSomething() {
46              return 123;
47          }
48  
49          /**
50           * Static method.
51           *
52           * @return the int
53           */
54          static int staticMethod() {
55              return -1;
56          }
57      }
58  
59      /**
60       * The Class Subclass.
61       */
62      public static class Subclass extends BaseClass {
63          /**
64           * Gets the single instance of Subclass.
65           *
66           * @return single instance of Subclass
67           */
68          BaseClass getInstance() {
69              return this;
70          }
71      }
72  
73      /**
74       * Mocked class extending JRE class.
75       *
76       * @param mock
77       *            the mock
78       *
79       * @throws Exception
80       *             the exception
81       */
82      @Test
83      void mockedClassExtendingJREClass(@Mocked SubclassOfJREClass mock) throws Exception {
84          // Mocked:
85          assertSame(mock, mock.append("a"));
86          assertSame(mock, mock.append('a'));
87          mock.close();
88  
89          // Not mocked:
90          Writer w = new Writer() {
91              @Override
92              public void write(@NonNull char[] cbuf, int off, int len) {
93              }
94  
95              @Override
96              public void flush() {
97              }
98  
99              @Override
100             public void close() {
101             }
102         };
103         assertSame(w, w.append("Test1"));
104         assertSame(w, w.append('b'));
105 
106         try {
107             new SubclassOfJREClass() {
108             }.close();
109         } catch (UnsupportedOperationException ignore) {
110         }
111     }
112 
113     /**
114      * Mocked class extending non JRE class.
115      *
116      * @param mock
117      *            the mock
118      */
119     @Test
120     void mockedClassExtendingNonJREClass(@Mocked final Subclass mock) {
121         new Expectations() {
122             {
123                 mock.doSomething();
124                 result = 45;
125                 times = 2;
126             }
127         };
128 
129         // Mocked:
130         assertEquals(45, mock.doSomething());
131         assertEquals(45, new Subclass().doSomething());
132 
133         // Not mocked:
134         assertEquals(123, new Subclass() {
135         }.doSomething());
136 
137         BaseClass b1 = new BaseClass();
138         BaseClass b2 = new BaseClass() {
139             @Override
140             protected int doSomething() {
141                 return super.doSomething() - 23;
142             }
143         };
144         assertEquals(123, b1.doSomething());
145         assertEquals(100, b2.doSomething());
146     }
147 
148     /**
149      * Cascading subclass with method returning cascaded base class instance.
150      *
151      * @param mock
152      *            the mock
153      */
154     @Test
155     void cascadingSubclassWithMethodReturningCascadedBaseClassInstance(@Mocked Subclass mock) {
156         // The subclass is already mocked at this point, when the cascaded instance gets created.
157         BaseClass cascaded = mock.getInstance();
158 
159         assertEquals(0, cascaded.doSomething());
160         assertEquals(0, mock.doSomething());
161     }
162 
163     /**
164      * Record expectation on static method from base class.
165      *
166      * @param unused
167      *            the unused
168      */
169     @Test
170     void recordExpectationOnStaticMethodFromBaseClass(@Mocked Subclass unused) {
171         new Expectations() {
172             {
173                 BaseClass.staticMethod();
174                 result = 123;
175             }
176         };
177 
178         assertEquals(123, BaseClass.staticMethod());
179     }
180 
181     /**
182      * The Class BaseClassWithConstructor.
183      */
184     static class BaseClassWithConstructor {
185         /**
186          * Instantiates a new base class with constructor.
187          *
188          * @param b
189          *            the b
190          */
191         BaseClassWithConstructor(@SuppressWarnings("unused") boolean b) {
192         }
193     }
194 
195     /**
196      * The Class DerivedClass.
197      */
198     static class DerivedClass extends BaseClassWithConstructor {
199 
200         /**
201          * Instantiates a new derived class.
202          */
203         protected DerivedClass() {
204             // TRYCATCHBLOCK instruction appears before call to super, which caused a VerifyError.
205             super(true);
206             try {
207                 doSomething();
208             } catch (RuntimeException ignore) {
209             }
210         }
211 
212         /**
213          * Do something.
214          */
215         private void doSomething() {
216         }
217     }
218 
219     /**
220      * Mock subclass with constructor containing try catch.
221      *
222      * @param mock
223      *            the mock
224      */
225     @Test
226     void mockSubclassWithConstructorContainingTryCatch(@Mocked DerivedClass mock) {
227         new DerivedClass();
228     }
229 
230     /**
231      * The Class Subclass2.
232      */
233     static class Subclass2 extends BaseClass {
234     }
235 
236     /**
237      * Record same method on different mocked subclasses.
238      *
239      * @param mock1
240      *            the mock 1
241      * @param mock2
242      *            the mock 2
243      */
244     @Test
245     void recordSameMethodOnDifferentMockedSubclasses(@Mocked final Subclass mock1, @Mocked final Subclass2 mock2) {
246         new Expectations() {
247             {
248                 mock1.doSomething();
249                 result = 1;
250                 mock2.doSomething();
251                 result = 2;
252             }
253         };
254 
255         assertEquals(1, mock1.doSomething());
256         assertEquals(2, mock2.doSomething());
257     }
258 
259     /**
260      * Record method on mocked base class but replay on subclass instance.
261      *
262      * @param baseMock
263      *            the base mock
264      */
265     @Test
266     void recordMethodOnMockedBaseClassButReplayOnSubclassInstance(@Mocked final BaseClass baseMock) {
267         new Expectations() {
268             {
269                 baseMock.doSomething();
270                 result = 45;
271             }
272         };
273 
274         Subclass derived = new Subclass();
275         assertEquals(123, derived.doSomething());
276         assertEquals(45, baseMock.doSomething());
277     }
278 
279     /**
280      * The Class BaseClassWithTwoConstructors.
281      */
282     static class BaseClassWithTwoConstructors {
283 
284         /** The value. */
285         final int value;
286 
287         /**
288          * Instantiates a new base class with two constructors.
289          */
290         @SuppressWarnings("unused")
291         BaseClassWithTwoConstructors() {
292             value = 1;
293         }
294 
295         /**
296          * Instantiates a new base class with two constructors.
297          *
298          * @param value
299          *            the value
300          */
301         BaseClassWithTwoConstructors(int value) {
302             this.value = value;
303         }
304     }
305 
306     /**
307      * The Class SubclassWithOneConstructor.
308      */
309     static class SubclassWithOneConstructor extends BaseClassWithTwoConstructors {
310         /**
311          * Instantiates a new subclass with one constructor.
312          */
313         SubclassWithOneConstructor() {
314             super(2);
315         }
316     }
317 
318     /**
319      * The Class SecondLevelSubclass1.
320      */
321     static final class SecondLevelSubclass1 extends SubclassWithOneConstructor {
322     }
323 
324     /**
325      * Mock direct subclass of base with two constructors but instantiate second level subclass.
326      *
327      * @param mock
328      *            the mock
329      */
330     @Test
331     void mockDirectSubclassOfBaseWithTwoConstructorsButInstantiateSecondLevelSubclass(
332             @Mocked SubclassWithOneConstructor mock) {
333         int value = new SecondLevelSubclass1().value;
334         assertEquals(2, value);
335     }
336 
337     /**
338      * The Class SecondLevelSubclass2.
339      */
340     static final class SecondLevelSubclass2 extends SubclassWithOneConstructor {
341     }
342 
343     /**
344      * Mock one subclass but instantiate unmocked sibling.
345      *
346      * @param mock
347      *            the mock
348      */
349     @Test
350     void mockOneSubclassButInstantiateUnmockedSibling(@Mocked SecondLevelSubclass1 mock) {
351         int value = new SecondLevelSubclass2().value;
352         assertEquals(2, value);
353     }
354 }