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