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 java.util.Arrays.asList;
9   
10  import static org.junit.jupiter.api.Assertions.assertEquals;
11  import static org.junit.jupiter.api.Assertions.assertNotNull;
12  import static org.junit.jupiter.api.Assertions.assertNull;
13  import static org.junit.jupiter.api.Assertions.assertSame;
14  
15  import jakarta.inject.Inject;
16  
17  import java.io.File;
18  import java.util.List;
19  import java.util.concurrent.Callable;
20  
21  import javax.naming.InitialContext;
22  import javax.naming.NamingException;
23  import javax.sql.DataSource;
24  
25  import org.junit.Before;
26  import org.junit.Test;
27  
28  /**
29   * The Class TestedClassWithConstructorDI4Test.
30   */
31  // TODO JWL 11/29/2025 This class is stuck to junit4 due to how injections work with junit5, support is missing
32  // currently that would allow this to move to junit5.
33  public final class TestedClassWithConstructorDI4Test {
34  
35      /**
36       * The Class GenericClass.
37       *
38       * @param <T>
39       *            the generic type
40       */
41      static class GenericClass<T> {
42          /**
43           * Do something.
44           *
45           * @return the t
46           */
47          T doSomething() {
48              return null;
49          }
50      }
51  
52      /**
53       * The Class TestedClass.
54       */
55      @SuppressWarnings("FieldMayBeFinal")
56      public static final class TestedClass {
57  
58          /** The go. */
59          final GenericClass<String> go;
60  
61          /** The values. */
62          final List<Integer> values;
63  
64          /** The action 1. */
65          final Callable<Number> action1;
66  
67          /** The action 2. */
68          private Callable<Number> action2;
69  
70          /** The action 3. */
71          private Callable<Number> action3;
72  
73          /** The database. */
74          private DataSource database;
75  
76          /**
77           * Instantiates a new tested class.
78           *
79           * @param go
80           *            the go
81           * @param values
82           *            the values
83           * @param actions
84           *            the actions
85           */
86          @SuppressWarnings("unchecked")
87          public TestedClass(GenericClass<String> go, List<Integer> values, Callable<Number>... actions) {
88              this.go = go;
89              this.values = values;
90              action1 = actions[0];
91              if (actions.length > 1) {
92                  action2 = actions[1];
93              }
94              if (actions.length > 2) {
95                  action3 = actions[2];
96              }
97  
98              try {
99                  // noinspection JNDIResourceOpenedButNotSafelyClosed
100                 InitialContext context = new InitialContext();
101                 database = (DataSource) context.lookup("testDB");
102                 context.close();
103             } catch (NamingException e) {
104                 throw new RuntimeException(e);
105             }
106         }
107     }
108 
109     /** The tested. */
110     @Tested
111     TestedClass tested;
112 
113     /** The action 1. */
114     @Injectable
115     Callable<Number> action1;
116 
117     /** The mock GO. */
118     @Injectable
119     final GenericClass<String> mockGO = new GenericClass<>(); // still mocked
120 
121     @Injectable
122     final List<Integer> numbers = asList(1, 2, 3); // not mocked when interface
123 
124     /** The jndi context. */
125     @Mocked
126     InitialContext jndiContext;
127 
128     /** The test DB. */
129     @Mocked
130     DataSource testDB;
131 
132     /**
133      * Record common expectations.
134      *
135      * @throws Exception
136      *             the exception
137      */
138     @Before
139     public void recordCommonExpectations() throws Exception {
140         new Expectations() {
141             {
142                 mockGO.doSomething();
143                 result = "test";
144                 minTimes = 0;
145             }
146         };
147         new Expectations() {
148             {
149                 jndiContext.lookup("testDB");
150                 result = testDB;
151             }
152         };
153     }
154 
155     /**
156      * Exercise tested object with values injected from mock fields.
157      */
158     @Test
159     public void exerciseTestedObjectWithValuesInjectedFromMockFields() {
160         assertNotNull(tested.go);
161         assertEquals(asList(1, 2, 3), tested.values);
162         assertSame(action1, tested.action1);
163         assertEquals("test", mockGO.doSomething());
164         assertNull(new GenericClass<String>().doSomething());
165     }
166 
167     /**
168      * Exercise tested object with values injected from mock parameters.
169      *
170      * @param action2
171      *            the action 2
172      * @param action3
173      *            the action 3
174      */
175     @Test
176     public void exerciseTestedObjectWithValuesInjectedFromMockParameters(@Injectable Callable<Number> action2,
177             @Injectable Callable<Number> action3) {
178         assertNotNull(tested.go);
179         assertEquals(asList(1, 2, 3), tested.values);
180         assertSame(action1, tested.action1);
181         assertSame(action2, tested.action2);
182         assertSame(action3, tested.action3);
183         assertEquals("test", mockGO.doSomething());
184         assertNull(new GenericClass().doSomething());
185     }
186 
187     /**
188      * Use mocked JRE classes during tested object creation.
189      *
190      * @param fileMock
191      *            the file mock
192      */
193     @Test
194     public void useMockedJREClassesDuringTestedObjectCreation(@Mocked File fileMock) {
195         assertNotNull(tested.database);
196         mockGO.doSomething();
197     }
198 
199     /**
200      * The Class TestedClass3.
201      */
202     static class TestedClass3 {
203 
204         /** The text. */
205         final String text;
206 
207         /** The dependency. */
208         final Runnable dependency;
209 
210         /** The other dep. */
211         @Inject
212         GenericClass<Integer> otherDep;
213 
214         /**
215          * Instantiates a new tested class 3.
216          *
217          * @param text
218          *            the text
219          * @param dependency
220          *            the dependency
221          */
222         TestedClass3(String text, Runnable dependency) {
223             this.text = text;
224             this.dependency = dependency;
225         }
226     }
227 
228     /** The tested 7. */
229     @Tested
230     TestedClass3 tested7;
231 
232     /** The text. */
233     @Injectable
234     final String text = null;
235 
236     /** The dependency. */
237     @Injectable
238     final Runnable dependency = null;
239 
240     /** The other dep. */
241     @Injectable
242     final GenericClass<Integer> otherDep = null;
243 
244     /**
245      * Inject nulls through constructor parameters and into required field.
246      */
247     @Test
248     public void injectNullsThroughConstructorParametersAndIntoRequiredField() {
249         assertNull(tested7.text);
250         assertNull(tested7.dependency);
251         assertNull(tested7.otherDep);
252     }
253 }