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.assertTrue;
10  
11  import java.awt.Graphics2D;
12  import java.util.concurrent.Callable;
13  
14  import javax.swing.SwingUtilities;
15  
16  import mockit.integration.junit5.JMockitExtension;
17  
18  import org.junit.jupiter.api.MethodOrderer.MethodName;
19  import org.junit.jupiter.api.Test;
20  import org.junit.jupiter.api.TestMethodOrder;
21  import org.junit.jupiter.api.extension.ExtendWith;
22  
23  /**
24   * The Class MultiThreadedExpectationsTest.
25   */
26  @ExtendWith(JMockitExtension.class)
27  @TestMethodOrder(MethodName.class)
28  class MultiThreadedExpectationsTest {
29  
30      /**
31       * The Class Collaborator.
32       */
33      static class Collaborator {
34  
35          /**
36           * Do something.
37           *
38           * @return the int
39           */
40          int doSomething() {
41              return -1;
42          }
43  
44          /**
45           * Do something else.
46           */
47          void doSomethingElse() {
48          }
49      }
50  
51      /** The mock. */
52      @Mocked
53      Collaborator mock;
54  
55      /**
56       * Use mocked collaborator from worker thread.
57       */
58      void useMockedCollaboratorFromWorkerThread() {
59          Thread worker = new Thread() {
60              @Override
61              public void run() {
62                  mock.doSomethingElse();
63              }
64          };
65          worker.start();
66          try {
67              worker.join();
68          } catch (InterruptedException ignore) {
69          }
70      }
71  
72      /**
73       * Use mocked object from worker thread while verifying expectation.
74       */
75      @Test
76      void useMockedObjectFromWorkerThreadWhileVerifyingExpectation() {
77          mock.doSomething();
78          mock.doSomething();
79  
80          new Verifications() {
81              {
82                  mock.doSomething();
83                  useMockedCollaboratorFromWorkerThread();
84                  times = 2;
85              }
86          };
87      }
88  
89      /**
90       * Use mocked object from worker thread while recording and verifying expectation.
91       */
92      @Test
93      void useMockedObjectFromWorkerThreadWhileRecordingAndVerifyingExpectation() {
94          new Expectations() {
95              {
96                  mock.doSomething();
97                  useMockedCollaboratorFromWorkerThread();
98                  result = 123;
99              }
100         };
101 
102         assertEquals(123, mock.doSomething());
103         mock.doSomethingElse();
104 
105         new VerificationsInOrder() {
106             {
107                 useMockedCollaboratorFromWorkerThread();
108                 mock.doSomething();
109                 mock.doSomethingElse();
110             }
111         };
112     }
113 
114     /**
115      * Replay recorded expectation from another thread.
116      *
117      * @throws Exception
118      *             the exception
119      */
120     @Test
121     void replayRecordedExpectationFromAnotherThread() throws Exception {
122         new Expectations() {
123             {
124                 mock.doSomething();
125             }
126         };
127 
128         Thread task = new Thread() {
129             @Override
130             public void run() {
131                 mock.doSomething();
132             }
133         };
134         task.start();
135         task.join();
136     }
137 
138     /**
139      * The Class Dependency.
140      */
141     static class Dependency {
142 
143         /**
144          * Do something.
145          */
146         void doSomething() {
147         }
148 
149         /**
150          * Do something else.
151          */
152         static void doSomethingElse() {
153         }
154     }
155 
156     /**
157      * Verify invocations replayed in another thread whose class is no longer mocked.
158      *
159      * @param dep
160      *            the dep
161      * @param g2D
162      *            the g 2 D
163      * @param runnable
164      *            the runnable
165      */
166     @Test
167     void verifyInvocationsReplayedInAnotherThreadWhoseClassIsNoLongerMocked(@Mocked final Dependency dep,
168             @Mocked final Graphics2D g2D, @Mocked final Runnable runnable) {
169         new Thread() {
170             @Override
171             public void run() {
172                 dep.doSomething();
173                 g2D.dispose();
174                 runnable.run();
175                 Dependency.doSomethingElse();
176             }
177         }.start();
178     }
179 
180     /**
181      * The Interface APublicInterface.
182      */
183     public interface APublicInterface {
184         /**
185          * Do something.
186          *
187          * @return true, if successful
188          */
189         boolean doSomething();
190     }
191 
192     /**
193      * Invoke method on mocked public interface from EDT.
194      *
195      * @param mock2
196      *            the mock 2
197      *
198      * @throws Exception
199      *             the exception
200      */
201     @Test
202     void invokeMethodOnMockedPublicInterfaceFromEDT(@Mocked final APublicInterface mock2) throws Exception {
203         new Expectations() {
204             {
205                 mock2.doSomething();
206                 result = true;
207             }
208         };
209 
210         SwingUtilities.invokeAndWait(() -> assertTrue(mock2.doSomething()));
211 
212         assertTrue(mock2.doSomething());
213     }
214 
215     /**
216      * The Class AnAbstractClass.
217      */
218     public abstract static class AnAbstractClass {
219         /**
220          * Do something.
221          *
222          * @return true, if successful
223          */
224         public abstract boolean doSomething();
225     }
226 
227     /**
228      * Invoke method on mocked abstract class from EDT.
229      *
230      * @param mock2
231      *            the mock 2
232      *
233      * @throws Exception
234      *             the exception
235      */
236     @Test
237     void invokeMethodOnMockedAbstractClassFromEDT(@Mocked final AnAbstractClass mock2) throws Exception {
238         new Expectations() {
239             {
240                 mock2.doSomething();
241                 result = true;
242             }
243         };
244 
245         SwingUtilities.invokeAndWait(() -> assertTrue(mock2.doSomething()));
246 
247         assertTrue(mock2.doSomething());
248     }
249 
250     /**
251      * Invoke method on mocked generic interface from EDT.
252      *
253      * @param mock2
254      *            the mock 2
255      *
256      * @throws Exception
257      *             the exception
258      */
259     @Test
260     void invokeMethodOnMockedGenericInterfaceFromEDT(@Mocked final Callable<Boolean> mock2) throws Exception {
261         new Expectations() {
262             {
263                 mock2.call();
264                 result = true;
265             }
266         };
267 
268         SwingUtilities.invokeAndWait(() -> {
269             try {
270                 assertTrue(mock2.call());
271             } catch (Exception e) {
272                 throw new RuntimeException(e);
273             }
274         });
275 
276         assertTrue(mock2.call());
277     }
278 }