1
2
3
4
5
6 package mockit;
7
8 import static org.junit.jupiter.api.Assertions.assertEquals;
9 import static org.junit.jupiter.api.Assertions.assertFalse;
10 import static org.junit.jupiter.api.Assertions.assertNotNull;
11 import static org.junit.jupiter.api.Assertions.assertNull;
12 import static org.junit.jupiter.api.Assertions.assertSame;
13 import static org.junit.jupiter.api.Assertions.assertTrue;
14
15 import java.lang.reflect.Method;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.Date;
20 import java.util.List;
21 import java.util.concurrent.Callable;
22
23 import javax.security.auth.callback.Callback;
24 import javax.security.auth.callback.CallbackHandler;
25 import javax.security.auth.callback.NameCallback;
26
27 import mockit.internal.expectations.invocation.MissingInvocation;
28 import mockit.internal.expectations.invocation.UnexpectedInvocation;
29
30 import org.junit.jupiter.api.Assertions;
31 import org.junit.jupiter.api.Disabled;
32 import org.junit.jupiter.api.Test;
33
34 @SuppressWarnings("JUnitTestMethodWithNoAssertions")
35 public final class MockAnnotationsTest {
36
37 final CodeUnderTest codeUnderTest = new CodeUnderTest();
38 boolean mockExecuted;
39
40 static class CodeUnderTest {
41 private final Collaborator dependency = new Collaborator();
42
43 void doSomething() {
44 dependency.provideSomeService();
45 }
46
47 long doSomethingElse(int i) {
48 return dependency.getThreadSpecificValue(i);
49 }
50
51 int performComputation(int a, boolean b) {
52 int i = dependency.getValue();
53 List<?> results = dependency.complexOperation(a, i);
54
55 if (b) {
56 dependency.setValue(i + results.size());
57 }
58
59 return i;
60 }
61 }
62
63 @SuppressWarnings("UnusedDeclaration")
64 static class Collaborator {
65 static Object xyz;
66 protected int value;
67
68 Collaborator() {
69 }
70
71 Collaborator(int value) {
72 this.value = value;
73 }
74
75 @Deprecated
76 private static String doInternal() {
77 return "123";
78 }
79
80 void provideSomeService() {
81 throw new RuntimeException("Real provideSomeService() called");
82 }
83
84 int getValue() {
85 return value;
86 }
87
88 void setValue(int value) {
89 this.value = value;
90 }
91
92 List<?> complexOperation(Object input1, Object... otherInputs) {
93 return input1 == null ? Collections.emptyList() : Arrays.asList(otherInputs);
94 }
95
96 final void simpleOperation(int a, String b, Date c) {
97 }
98
99 long getThreadSpecificValue(int i) {
100 return Thread.currentThread().getId() + i;
101 }
102 }
103
104
105
106 static class MockCollaborator1 extends MockUp<Collaborator> {
107 @Mock
108 void provideSomeService() {
109 }
110 }
111
112 @Test
113 public void mockWithNoExpectationsPassingMockInstance() {
114 new MockCollaborator1();
115
116 codeUnderTest.doSomething();
117 }
118
119
120 @Disabled("Mocked method must be checked if it exists in the calling class.")
121 @Test
122 public void attemptToSetUpMockForClassLackingAMatchingRealMethod() {
123 Assertions.assertThrows(IllegalArgumentException.class, () -> new MockForClassWithoutRealMethod());
124 }
125
126 static final class MockForClassWithoutRealMethod extends MockUp<Collaborator> {
127 @Mock
128 void noMatchingRealMethod() {
129 }
130 }
131
132 public interface GenericInterface<T> {
133 void method(T t);
134
135 String method(int[] ii, T l, String[][] ss, T[] ll);
136 }
137
138 public interface NonGenericSubInterface extends GenericInterface<Long> {
139 }
140
141 public static final class MockForNonGenericSubInterface extends MockUp<NonGenericSubInterface> {
142 @Mock(invocations = 1)
143 public void method(Long l) {
144 assertTrue(l > 0);
145 }
146
147 @Mock
148 public String method(int[] ii, Long l, String[][] ss, Long[] ll) {
149 assertTrue(ii.length > 0 && l > 0);
150 return "mocked";
151 }
152 }
153
154 @Test
155 public void mockMethodOfSubInterfaceWithGenericTypeArgument() {
156 NonGenericSubInterface mock = new MockForNonGenericSubInterface().getMockInstance();
157
158 mock.method(123L);
159 assertEquals("mocked", mock.method(new int[] { 1 }, 45L, null, null));
160 }
161
162 @Test
163 public void mockMethodOfGenericInterfaceWithArrayAndGenericTypeArgument() {
164 GenericInterface<Long> mock = new MockUp<GenericInterface<Long>>() {
165 @Mock
166 String method(int[] ii, Long l, String[][] ss, Long[] tt) {
167 assertTrue(ii.length > 0 && l > 0);
168 return "mocked";
169 }
170 }.getMockInstance();
171
172 assertEquals("mocked", mock.method(new int[] { 1 }, 45L, null, null));
173 }
174
175 @Test
176 public void setUpMocksFromInnerMockClassWithMockConstructor() {
177 new MockCollaborator4();
178 assertFalse(mockExecuted);
179
180 new CodeUnderTest().doSomething();
181
182 assertTrue(mockExecuted);
183 }
184
185 class MockCollaborator4 extends MockUp<Collaborator> {
186 @Mock
187 void $init() {
188 mockExecuted = true;
189 }
190
191 @Mock
192 void provideSomeService() {
193 }
194 }
195
196
197
198 @Test
199 public void setUpMocksContainingExpectations() {
200 new MockCollaboratorWithExpectations();
201
202 int result = codeUnderTest.performComputation(2, true);
203
204 assertEquals(0, result);
205 }
206
207 static class MockCollaboratorWithExpectations extends MockUp<Collaborator> {
208 @Mock(minInvocations = 1)
209 int getValue() {
210 return 0;
211 }
212
213 @Mock(maxInvocations = 2)
214 void setValue(int value) {
215 assertEquals(1, value);
216 }
217
218 @Mock
219 List<?> complexOperation(Object input1, Object... otherInputs) {
220 int i = (Integer) otherInputs[0];
221 assertEquals(0, i);
222
223 List<Integer> values = new ArrayList<Integer>();
224 values.add((Integer) input1);
225 return values;
226 }
227
228 @Mock(invocations = 0)
229 void provideSomeService() {
230 }
231 }
232
233
234 @Disabled("Determination of the number of method calls is not yet implemented.")
235 @Test
236 public void setUpMockWithMinInvocationsExpectationButFailIt() {
237 Assertions.assertThrows(MissingInvocation.class, () -> new MockCollaboratorWithMinInvocationsExpectation());
238 }
239
240 static class MockCollaboratorWithMinInvocationsExpectation extends MockUp<Collaborator> {
241 @Mock(minInvocations = 2)
242 int getValue() {
243 return 1;
244 }
245 }
246
247
248 @Disabled("Determination of the number of method calls is not yet implemented.")
249 @Test
250 public void setUpMockWithMaxInvocationsExpectationButFailIt() {
251 new MockCollaboratorWithMaxInvocationsExpectation();
252
253 Assertions.assertThrows(UnexpectedInvocation.class, () -> new Collaborator().setValue(23));
254 }
255
256 static class MockCollaboratorWithMaxInvocationsExpectation extends MockUp<Collaborator> {
257 @Mock(maxInvocations = 0)
258 void setValue(int v) {
259 assertEquals(23, v);
260 }
261 }
262
263
264 @Disabled("Determination of the number of method calls is not yet implemented.")
265 @Test
266 public void setUpMockWithInvocationsExpectationButFailIt() {
267 new MockCollaboratorWithInvocationsExpectation();
268
269 Assertions.assertThrows(UnexpectedInvocation.class, () -> {
270 codeUnderTest.doSomething();
271 codeUnderTest.doSomething();
272 });
273 }
274
275 static class MockCollaboratorWithInvocationsExpectation extends MockUp<Collaborator> {
276 @Mock(invocations = 1)
277 void provideSomeService() {
278 }
279 }
280
281
282
283 @Test
284 public void setUpReentrantMock() {
285 new MockCollaboratorWithReentrantMock();
286
287 Assertions.assertThrows(RuntimeException.class, () -> codeUnderTest.doSomething());
288 }
289
290 static class MockCollaboratorWithReentrantMock extends MockUp<Collaborator> {
291 @Mock
292 int getValue() {
293 return 123;
294 }
295
296 @Mock(invocations = 1)
297 void provideSomeService(Invocation inv) {
298 inv.proceed();
299 }
300 }
301
302
303
304 @Test
305 public void setUpMockForConstructor() {
306 new MockCollaboratorWithConstructorMock();
307
308 new Collaborator(5);
309 }
310
311 static class MockCollaboratorWithConstructorMock extends MockUp<Collaborator> {
312 @Mock(invocations = 1)
313 void $init(int value) {
314 assertEquals(5, value);
315 }
316 }
317
318 @Test
319 public void setUpMockForStaticMethod() {
320 new MockCollaboratorForStaticMethod();
321
322
323 Collaborator.doInternal();
324 }
325
326 static class MockCollaboratorForStaticMethod extends MockUp<Collaborator> {
327 @Mock(invocations = 1)
328 static String doInternal() {
329 return "";
330 }
331 }
332
333 @Test
334 public void setUpMockForSubclassConstructor() {
335 new MockSubCollaborator();
336
337 new SubCollaborator(31);
338 }
339
340 static class SubCollaborator extends Collaborator {
341 SubCollaborator(int i) {
342 throw new RuntimeException(String.valueOf(i));
343 }
344
345 @Override
346 void provideSomeService() {
347 value = 123;
348 }
349 }
350
351 static class MockSubCollaborator extends MockUp<SubCollaborator> {
352 @Mock(invocations = 1)
353 void $init(int i) {
354 assertEquals(31, i);
355 }
356
357 @SuppressWarnings("UnusedDeclaration")
358 native void doNothing();
359 }
360
361 @Test
362 public void setUpMocksForClassHierarchy() {
363 new MockUp<SubCollaborator>() {
364 @Mock
365 void $init(Invocation inv, int i) {
366 assertNotNull(inv.getInvokedInstance());
367 assertTrue(i > 0);
368 }
369
370 @Mock
371 void provideSomeService(Invocation inv) {
372 SubCollaborator it = inv.getInvokedInstance();
373 it.value = 45;
374 }
375
376 @Mock
377 int getValue(Invocation inv) {
378 assertNotNull(inv.getInvokedInstance());
379
380
381
382
383 return 123;
384 }
385 };
386
387 SubCollaborator collaborator = new SubCollaborator(123);
388 collaborator.provideSomeService();
389 assertEquals(45, collaborator.value);
390 assertEquals(123, collaborator.getValue());
391 }
392
393 @Test
394 public void mockNativeMethodInClassWithRegisterNatives() {
395
396 Assertions.assertThrows(UnsupportedOperationException.class, () -> {
397 MockSystem mockUp = new MockSystem();
398 assertEquals(0, System.nanoTime());
399
400 mockUp.onTearDown();
401 assertTrue(System.nanoTime() > 0);
402 });
403 }
404
405 static class MockSystem extends MockUp<System> {
406 @Mock
407 public static long nanoTime() {
408 return 0;
409 }
410 }
411
412 @Test
413 public void mockNativeMethodInClassWithoutRegisterNatives() throws Exception {
414
415 Assertions.assertThrows(UnsupportedOperationException.class, () -> {
416 MockFloat mockUp = new MockFloat();
417 assertEquals(0.0, Float.intBitsToFloat(2243019), 0.0);
418
419 mockUp.onTearDown();
420 assertTrue(Float.intBitsToFloat(2243019) > 0);
421 });
422 }
423
424 static class MockFloat extends MockUp<Float> {
425 @SuppressWarnings("UnusedDeclaration")
426 @Mock
427 public static float intBitsToFloat(int bits) {
428 return 0;
429 }
430 }
431
432 @Test
433 public void setUpMockForJREClass() {
434 MockThread mockThread = new MockThread();
435
436 Thread.currentThread().interrupt();
437
438 assertTrue(mockThread.interrupted);
439 }
440
441 public static class MockThread extends MockUp<Thread> {
442 boolean interrupted;
443
444 @Mock(invocations = 1)
445 public void interrupt() {
446 interrupted = true;
447 }
448 }
449
450
451
452 static class ClassWithStaticInitializers {
453 static String str = "initialized";
454 static final Object obj = new Object();
455
456 static {
457 System.exit(1);
458 }
459
460 static void doSomething() {
461 }
462
463 static {
464 try {
465 Class.forName("NonExistentClass");
466 } catch (ClassNotFoundException e) {
467 e.printStackTrace();
468 }
469 }
470 }
471
472 @Test
473 public void mockStaticInitializer() {
474 new MockUp<ClassWithStaticInitializers>() {
475 @Mock(invocations = 1)
476 void $clinit() {
477 }
478 };
479
480 ClassWithStaticInitializers.doSomething();
481
482 assertNull(ClassWithStaticInitializers.str);
483 assertNull(ClassWithStaticInitializers.obj);
484 }
485
486 static class AnotherClassWithStaticInitializers {
487 static {
488 System.exit(1);
489 }
490
491 static void doSomething() {
492 throw new RuntimeException();
493 }
494 }
495
496 @Test
497 public void stubOutStaticInitializer() throws Exception {
498 new MockForClassWithInitializer();
499
500 AnotherClassWithStaticInitializers.doSomething();
501 }
502
503 static class MockForClassWithInitializer extends MockUp<AnotherClassWithStaticInitializers> {
504 @Mock
505 void $clinit() {
506 }
507
508 @Mock(minInvocations = 1, maxInvocations = 1)
509 void doSomething() {
510 }
511 }
512
513 static class YetAnotherClassWithStaticInitializer {
514 static {
515 System.loadLibrary("none.dll");
516 }
517
518 static void doSomething() {
519 }
520 }
521
522 static class MockForYetAnotherClassWithInitializer extends MockUp<YetAnotherClassWithStaticInitializer> {
523 @Mock
524 void $clinit() {
525 }
526 }
527
528
529
530 @Test
531 public void stubOutStaticInitializerWithEmptyMockClass() throws Exception {
532 new MockForYetAnotherClassWithInitializer();
533
534 YetAnotherClassWithStaticInitializer.doSomething();
535 }
536
537 @Test
538 public void mockJREInterface() throws Exception {
539 CallbackHandler callbackHandler = new MockCallbackHandler().getMockInstance();
540
541 callbackHandler.handle(new Callback[] { new NameCallback("Enter name:") });
542 }
543
544 public static class MockCallbackHandler extends MockUp<CallbackHandler> {
545 @Mock(invocations = 1)
546 public void handle(Callback[] callbacks) {
547 assertEquals(1, callbacks.length);
548 assertTrue(callbacks[0] instanceof NameCallback);
549 }
550 }
551
552 @Test
553 public void mockJREInterfaceWithMockUp() throws Exception {
554 CallbackHandler callbackHandler = new MockUp<CallbackHandler>() {
555 @Mock(invocations = 1)
556 void handle(Callback[] callbacks) {
557 assertEquals(1, callbacks.length);
558 assertTrue(callbacks[0] instanceof NameCallback);
559 }
560 }.getMockInstance();
561
562 callbackHandler.handle(new Callback[] { new NameCallback("Enter name:") });
563 }
564
565 public interface AnInterface {
566 int doSomething();
567 }
568
569 @Test
570 public void mockPublicInterfaceWithMockUpHavingInvocationParameter() {
571 AnInterface obj = new MockUp<AnInterface>() {
572 @Mock
573 int doSomething(Invocation inv) {
574 assertNotNull(inv.getInvokedInstance());
575 return 122 + inv.getInvocationCount();
576 }
577 }.getMockInstance();
578
579 assertEquals(123, obj.doSomething());
580 }
581
582 abstract static class AnAbstractClass {
583 abstract int doSomething();
584 }
585
586 @Test
587 public <A extends AnAbstractClass> void mockAbstractClassWithMockForAbstractMethodHavingInvocationParameter() {
588 final AnAbstractClass obj = new AnAbstractClass() {
589 @Override
590 int doSomething() {
591 return 0;
592 }
593 };
594
595 new MockUp<A>() {
596 @Mock
597 int doSomething(Invocation inv) {
598 assertSame(obj, inv.getInvokedInstance());
599 Method invokedMethod = inv.getInvokedMember();
600 assertTrue(AnAbstractClass.class.isAssignableFrom(invokedMethod.getDeclaringClass()));
601 return 123;
602 }
603 };
604
605 assertEquals(123, obj.doSomething());
606 }
607
608 interface AnotherInterface {
609 int doSomething();
610 }
611
612 AnotherInterface interfaceInstance;
613
614 @Test
615 public void attemptToProceedIntoInterfaceImplementation() {
616 interfaceInstance = new MockUp<AnotherInterface>() {
617 @Mock
618 int doSomething(Invocation inv) {
619 return inv.proceed();
620 }
621 }.getMockInstance();
622
623 Throwable exception = Assertions.assertThrows(UnsupportedOperationException.class,
624 () -> interfaceInstance.doSomething());
625 assertEquals("Cannot proceed into abstract/interface method", exception.getMessage());
626 }
627
628 @Test
629 public void mockNonPublicInterfaceWithMockUpHavingInvocationParameter() {
630 interfaceInstance = new MockUp<AnotherInterface>() {
631 @Mock
632 int doSomething(Invocation inv) {
633 AnotherInterface invokedInstance = inv.getInvokedInstance();
634 assertSame(interfaceInstance, invokedInstance);
635
636 int invocationCount = inv.getInvocationCount();
637 assertTrue(invocationCount > 0);
638
639 return invocationCount == 1 ? invokedInstance.doSomething() : 123;
640 }
641 }.getMockInstance();
642
643 assertEquals(123, interfaceInstance.doSomething());
644 }
645
646 @Test
647 public void mockGenericInterfaceWithMockUpHavingInvocationParameter() throws Exception {
648 Callable<String> mock = new MockUp<Callable<String>>() {
649 @Mock
650 String call(Invocation inv) {
651 return "mocked";
652 }
653 }.getMockInstance();
654
655 assertEquals("mocked", mock.call());
656 }
657
658 static class GenericClass<T> {
659 T doSomething() {
660 return null;
661 }
662 }
663
664 @Test
665 public void mockGenericClassWithMockUpHavingInvocationParameter() {
666 new MockUp<GenericClass<String>>() {
667 @Mock
668 String doSomething(Invocation inv) {
669 return "mocked";
670 }
671 };
672
673 GenericClass<String> mock = new GenericClass<String>();
674 assertEquals("mocked", mock.doSomething());
675 }
676
677 @Test
678 public void stubbedOutAnnotatedMethodInMockedClass() throws Exception {
679 new MockCollaborator7();
680
681 assertTrue(Collaborator.class.getDeclaredMethod("doInternal").isAnnotationPresent(Deprecated.class));
682 }
683
684 static class MockCollaborator7 extends MockUp<Collaborator> {
685 @Mock
686 String doInternal() {
687 return null;
688 }
689
690 @Mock
691 void provideSomeService() {
692 }
693 }
694
695 @Test
696 public void concurrentMock() throws Exception {
697 new MockUp<Collaborator>() {
698 @Mock
699 long getThreadSpecificValue(int i) {
700 return Thread.currentThread().getId() + 123;
701 }
702 };
703
704 Thread[] threads = new Thread[5];
705
706 for (int i = 0; i < threads.length; i++) {
707 threads[i] = new Thread() {
708 @Override
709 public void run() {
710 long threadSpecificValue = Thread.currentThread().getId() + 123;
711 long actualValue = new CodeUnderTest().doSomethingElse(0);
712 assertEquals(threadSpecificValue, actualValue);
713 }
714 };
715 }
716
717 for (Thread thread : threads) {
718 thread.start();
719 }
720 for (Thread thread : threads) {
721 thread.join();
722 }
723 }
724
725 @Test
726 public void mockUpAffectsInstancesOfSpecifiedSubclassAndNotOfBaseClass() {
727 new MockUpForSubclass();
728
729
730 assertEquals(123, new SubCollaborator(5).getValue());
731
732
733
734 assertEquals("mocked", Collaborator.doInternal());
735
736
737 assertEquals(62, new Collaborator(62).getValue());
738 }
739
740 static class MockUpForSubclass extends MockUp<SubCollaborator> {
741 @Mock
742 void $init(int i) {
743 }
744
745 @Mock
746 String doInternal() {
747 return "mocked";
748 }
749
750 @Mock
751 int getValue() {
752 return 123;
753 }
754 }
755 }