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