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   
7   import org.junit.jupiter.api.BeforeEach;
8   import org.junit.jupiter.api.Test;
9   
10  /**
11   * The Class ClassInitializationTest.
12   */
13  final class ClassInitializationTest {
14  
15      static final class ClassWhichFailsAtInitialization {
16          static {
17              // noinspection ConstantConditions
18              if (true) {
19                  throw new AssertionError();
20              }
21          }
22  
23          static int value() {
24              return 0;
25          }
26      }
27  
28      @Test
29      public void usingExpectations(@Mocked(stubOutClassInitialization = true) ClassWhichFailsAtInitialization unused) {
30          new Expectations() {
31              {
32                  ClassWhichFailsAtInitialization.value();
33                  result = 1;
34              }
35          };
36  
37          assertEquals(1, ClassWhichFailsAtInitialization.value());
38      }
39  
40      /**
41       * The Class ClassWithStaticInitializer.
42       */
43      static class ClassWithStaticInitializer {
44  
45          /** The Constant CONSTANT. */
46          static final Object CONSTANT = "not a compile-time constant";
47  
48          /** The variable. */
49          static String variable;
50          static {
51              variable = doSomething();
52          }
53  
54          /**
55           * Do something.
56           *
57           * @return the string
58           */
59          static String doSomething() {
60              return "real value";
61          }
62      }
63  
64      /**
65       * Mock class with static initializer.
66       *
67       * @param mocked
68       *            the mocked
69       */
70      @Test
71      void mockClassWithStaticInitializerNotStubbedOut(@Mocked ClassWithStaticInitializer mocked) {
72          // noinspection ConstantJUnitAssertArgument
73          assertNotNull(ClassWithStaticInitializer.CONSTANT);
74          assertNull(ClassWithStaticInitializer.doSomething());
75          assertEquals("real value", ClassWithStaticInitializer.variable);
76      }
77  
78      static class AnotherClassWithStaticInitializer {
79          static final Object CONSTANT = "not a compile-time constant";
80          static {
81              doSomething();
82          }
83  
84          static void doSomething() {
85              throw new UnsupportedOperationException("must not execute");
86          }
87  
88          int getValue() {
89              return -1;
90          }
91      }
92  
93      @Test
94      public void mockClassWithStaticInitializerStubbedOut(
95              @Mocked(stubOutClassInitialization = true) AnotherClassWithStaticInitializer mockAnother) {
96          // noinspection ConstantJUnitAssertArgument
97          assertNull(AnotherClassWithStaticInitializer.CONSTANT);
98          AnotherClassWithStaticInitializer.doSomething();
99          assertEquals(0, mockAnother.getValue());
100     }
101 
102     /**
103      * The Class ClassWhichCallsStaticMethodFromInitializer.
104      */
105     static class ClassWhichCallsStaticMethodFromInitializer {
106         static {
107             String s = someValue();
108             s.length();
109         }
110 
111         /**
112          * Some value.
113          *
114          * @return the string
115          */
116         static String someValue() {
117             return "some value";
118         }
119     }
120 
121     /**
122      * Mock uninitialized class.
123      *
124      * @param unused
125      *            the unused
126      */
127     @Test
128     void mockUninitializedClass(@Mocked ClassWhichCallsStaticMethodFromInitializer unused) {
129         assertNull(ClassWhichCallsStaticMethodFromInitializer.someValue());
130     }
131 
132     /**
133      * The Interface BaseType.
134      */
135     public interface BaseType {
136         /**
137          * Some value.
138          *
139          * @return the string
140          */
141         String someValue();
142     }
143 
144     /**
145      * The Class NestedImplementationClass.
146      */
147     static final class NestedImplementationClass implements BaseType {
148         static {
149             new NestedImplementationClass().someValue().length();
150         }
151 
152         @Override
153         public String someValue() {
154             return "some value";
155         }
156     }
157 
158     /**
159      * Load nested implementation class.
160      */
161     @BeforeEach
162     void loadNestedImplementationClass() {
163         // Ensure the class gets loaded, but not initialized, before it gets mocked.
164         // The HotSpot VM would (for some reason) already have loaded it, but the J9 VM would not.
165         NestedImplementationClass.class.getName();
166     }
167 
168     /**
169      * Mock uninitialized implementation class.
170      *
171      * @param mockBase
172      *            the mock base
173      */
174     @Test
175     void mockUninitializedImplementationClass(@Capturing BaseType mockBase) {
176         BaseType obj = new NestedImplementationClass();
177 
178         assertNull(obj.someValue());
179     }
180 
181     /**
182      * The Class Dependency.
183      */
184     static class Dependency {
185         /**
186          * Creates the.
187          *
188          * @return the dependency
189          */
190         static Dependency create() {
191             return null;
192         }
193     }
194 
195     /**
196      * The Class Dependent.
197      */
198     static class Dependent {
199 
200         /** The Constant DEPENDENCY. */
201         static final Dependency DEPENDENCY = Dependency.create();
202         static {
203             DEPENDENCY.toString();
204         }
205     }
206 
207     /**
208      * The Class AnotherDependent.
209      */
210     static class AnotherDependent {
211 
212         /** The Constant DEPENDENCY. */
213         static final Dependency DEPENDENCY = Dependency.create();
214         static {
215             DEPENDENCY.toString();
216         }
217     }
218 
219     /** The dependency. */
220     @Mocked
221     Dependency dependency;
222 
223     /** The dependent. */
224     @Mocked
225     Dependent dependent;
226 
227     /**
228      * Mock another dependent class.
229      *
230      * @param anotherDependent
231      *            the another dependent
232      */
233     @Test
234     void mockAnotherDependentClass(@Mocked AnotherDependent anotherDependent) {
235         assertNotNull(Dependent.DEPENDENCY);
236         assertNotNull(AnotherDependent.DEPENDENCY);
237     }
238 
239     /**
240      * The Interface BaseInterface.
241      */
242     public interface BaseInterface {
243         /** The do not remove. */
244         Object DO_NOT_REMOVE = "Testing";
245     }
246 
247     /**
248      * The Interface SubInterface.
249      */
250     public interface SubInterface extends BaseInterface {
251     }
252 
253     /** The mock. */
254     @Mocked
255     SubInterface mock;
256 
257     /**
258      * Verify class initializer for mocked base interface.
259      */
260     @Test
261     void verifyClassInitializerForMockedBaseInterface() {
262         assertNotNull(mock);
263         assertEquals("Testing", BaseInterface.DO_NOT_REMOVE);
264     }
265 
266     /**
267      * The Class ClassWhichCallsMethodOnItselfFromInitializer.
268      */
269     static final class ClassWhichCallsMethodOnItselfFromInitializer {
270 
271         /** The Constant value. */
272         static final Integer value = value();
273 
274         /**
275          * Value.
276          *
277          * @return the integer
278          */
279         static Integer value() {
280             return null;
281         }
282     }
283 
284     /**
285      * Mock class which calls method on itself from initializer.
286      *
287      * @param unused
288      *            the unused
289      */
290     @Test
291     void mockClassWhichCallsMethodOnItselfFromInitializerWithoutStubbingOutTheInitializer(
292             @Mocked ClassWhichCallsMethodOnItselfFromInitializer unused) {
293         assertNotNull(ClassWhichCallsMethodOnItselfFromInitializer.value());
294         assertNull(ClassWhichCallsMethodOnItselfFromInitializer.value);
295     }
296 
297     /**
298      * The Interface InterfaceWithStaticInitializer.
299      */
300     interface InterfaceWithStaticInitializer {
301         /** The constant. */
302         Object CONSTANT = "test";
303     }
304 
305     /**
306      * The Class AbstractImpl.
307      */
308     @SuppressWarnings({ "AbstractClassWithoutAbstractMethods", "StaticInheritance" })
309     public abstract static class AbstractImpl implements InterfaceWithStaticInitializer {
310     }
311 
312     /**
313      * Mock abstract class implementing interface with static initializer.
314      *
315      * @param mock2
316      *            the mock 2
317      */
318     // failed on JDK 9+ only
319     @Test
320     void mockAbstractClassImplementingInterfaceWithStaticInitializer(@Mocked AbstractImpl mock2) {
321         assertEquals("test", InterfaceWithStaticInitializer.CONSTANT);
322     }
323 }