1
2
3
4
5
6 package mockit;
7
8 import static java.util.Arrays.asList;
9 import static java.util.Collections.singletonList;
10
11 import static mockit.ExpectationsWithArgMatchersTest.Delegates.collectionElement;
12 import static org.hamcrest.CoreMatchers.equalTo;
13 import static org.hamcrest.CoreMatchers.hasItem;
14 import static org.hamcrest.Matchers.containsInAnyOrder;
15 import static org.junit.jupiter.api.Assertions.assertEquals;
16 import static org.junit.jupiter.api.Assertions.assertFalse;
17 import static org.junit.jupiter.api.Assertions.assertNull;
18 import static org.junit.jupiter.api.Assertions.assertSame;
19 import static org.junit.jupiter.api.Assertions.assertTrue;
20
21 import java.security.cert.Certificate;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Date;
25 import java.util.List;
26
27 import mockit.integration.junit5.ExpectedException;
28 import mockit.integration.junit5.JMockitExtension;
29 import mockit.internal.expectations.invocation.MissingInvocation;
30
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.extension.ExtendWith;
33
34
35
36
37 @ExtendWith(JMockitExtension.class)
38 class ExpectationsWithArgMatchersTest {
39
40
41
42
43 @SuppressWarnings("unused")
44 static class Collaborator {
45
46
47
48
49
50
51
52 void setValue(int value) {
53 }
54
55
56
57
58
59
60
61 void setValue(double value) {
62 }
63
64
65
66
67
68
69
70
71
72 boolean setValue(float value) {
73 return false;
74 }
75
76
77
78
79
80
81
82 void setValue(char value) {
83 }
84
85
86
87
88
89
90
91 void setValue(String value) {
92 }
93
94
95
96
97
98
99
100
101
102 void setValues(char c, boolean b) {
103 }
104
105
106
107
108
109
110
111 void setValues(String[] values) {
112 }
113
114
115
116
117
118
119
120 void setTextualValues(Collection<String> values) {
121 }
122
123
124
125
126
127
128
129 void doSomething(Integer i) {
130 }
131
132
133
134
135
136
137
138
139
140 boolean doSomething(String s) {
141 return false;
142 }
143
144
145
146
147
148
149
150
151
152
153
154 final void simpleOperation(int a, String b, Date c) {
155 }
156
157
158
159
160
161
162
163 void setValue(Certificate cert) {
164 }
165
166
167
168
169
170
171
172 void setValue(Exception ex) {
173 }
174
175 void setIntValue(int i) {
176 }
177
178
179
180
181
182
183
184
185
186 String useObject(Object arg) {
187 return "";
188 }
189 }
190
191
192 @Mocked
193 Collaborator mock;
194
195
196
197
198 @Test
199 @ExpectedException(value = MissingInvocation.class, expectedMessages = { "setValue",
200 "a numeric value within 0.01 of 2.3", "instead got", "setValue(2.32)" })
201 void verifyExpectationNumericEqualityMatcherButFailToMatchOnReplay() {
202 mock.setValue(2.32);
203
204 new Verifications() {
205 {
206 mock.setValue(withEqual(2.3, 0.01));
207 }
208 };
209 }
210
211
212
213
214 @Test
215 @ExpectedException(MissingInvocation.class)
216 void verifyExpectationUsingNumericEqualityMatcherButReplayWithNonNumericParameterType() {
217 mock.useObject('2');
218
219 new Verifications() {
220 {
221 mock.useObject(withEqual(2.3, 0.01));
222 }
223 };
224 }
225
226
227
228
229 @Test
230 @ExpectedException(value = MissingInvocation.class, expectedMessages = { "(not 2)", "got", "(2)" })
231 void verifyExpectationUsingInequalityMatcherButFailToMatchOnReplay() {
232 mock.setValue(2);
233
234 new Verifications() {
235 {
236 mock.setValue(withNotEqual(2));
237 }
238 };
239 }
240
241
242
243
244 @Test
245 void verifyExpectationsUsingNumericEqualityMatchers() {
246 new Expectations() {
247 {
248 mock.setValue(withEqual(2.0F, 0.01F));
249 result = true;
250 mock.setValue(withEqual(2.0F, 0.05F));
251 result = false;
252 }
253 };
254
255 assertFalse(mock.setValue(2.0F));
256 assertFalse(mock.setValue(2.05F));
257 }
258
259
260
261
262 @Test
263 void recordExpectationWithDelegateWithoutTheParameterType() {
264 new Expectations() {
265 {
266 mock.useObject(with(new Delegate() {
267 @SuppressWarnings("unused")
268 boolean delegate(Object arg) {
269 return "test".equals(arg);
270 }
271 }));
272 }
273 };
274
275 String result = mock.useObject("test");
276
277 assertNull(result);
278 }
279
280
281
282
283
284
285
286 static final class CollectionElementDelegate<T> implements Delegate<Collection<T>> {
287
288
289 private final T item;
290
291
292
293
294
295
296
297 CollectionElementDelegate(T item) {
298 this.item = item;
299 }
300
301
302
303
304
305
306
307
308
309 @SuppressWarnings("unused")
310 boolean hasItem(Collection<T> items) {
311 return items.contains(item);
312 }
313 }
314
315
316
317
318 @SuppressWarnings("unused")
319 static final class Delegates {
320
321
322
323
324
325
326
327
328
329
330
331 static <T> Delegate<Collection<T>> collectionElement(T item) {
332 return new CollectionElementDelegate<>(item);
333 }
334 }
335
336
337
338
339 @Test
340 void expectInvocationsWithNamedDelegateMatcher() {
341 new Expectations() {
342 {
343 mock.setTextualValues(with(collectionElement("B")));
344 }
345 };
346
347 List<String> values = asList("a", "B", "c");
348 mock.setTextualValues(values);
349 }
350
351 @Test
352 void expectInvocationsWithHamcrestMatcher() {
353 new Expectations() {
354 {
355 mock.setTextualValues(this.<Collection<String>> withArgThat(hasItem("B")));
356 }
357 };
358
359 List<String> values = asList("a", "B", "c");
360 mock.setTextualValues(values);
361 }
362
363 @Test
364 void expectInvocationsWithHamcrestMatcher2() {
365 new Expectations() {
366 {
367 mock.setTextualValues(withArgThat(containsInAnyOrder("B", "c", "a")));
368 }
369 };
370
371 List<String> values = asList("a", "B", "c");
372 mock.setTextualValues(values);
373 }
374
375 @Test
376 void expectInvocationWithMatcherContainingAnotherMatcher() {
377 new Expectations() {
378 {
379 mock.setIntValue(withArgThat(equalTo(3)));
380 }
381 };
382
383 mock.setIntValue(3);
384 }
385
386
387
388
389 @Test
390 void useMockedMethodBeforeRecordingExpectationWithArgumentMatcher() {
391 assertFalse(mock.doSomething("abc"));
392
393 new Expectations() {
394 {
395 mock.doSomething(anyString);
396 result = true;
397 }
398 };
399
400 assertTrue(mock.doSomething("xyz"));
401 assertTrue(mock.doSomething("abc"));
402 }
403
404
405
406
407 @Test
408 void recordExpectationsUsingTheAnyFieldsForParameterOfTypeObject() {
409 new Expectations() {
410 {
411 mock.useObject(anyString);
412 result = "String";
413 mock.useObject(anyInt);
414 result = "int";
415 mock.useObject(anyByte);
416 result = "byte";
417 mock.useObject(anyShort);
418 result = "short";
419 mock.useObject(anyLong);
420 result = "long";
421 mock.useObject(anyBoolean);
422 result = "boolean";
423 mock.useObject(anyChar);
424 result = "char";
425 mock.useObject(anyFloat);
426 result = "float";
427 mock.useObject(anyDouble);
428 result = "double";
429 mock.useObject(any);
430 result = "Object";
431 }
432 };
433
434 assertInvocationsWithArgumentsOfDifferentTypesToMethodAcceptingAnyObject();
435 }
436
437
438
439
440 void assertInvocationsWithArgumentsOfDifferentTypesToMethodAcceptingAnyObject() {
441 assertEquals("String", mock.useObject("test"));
442 assertEquals("String", mock.useObject(null));
443 assertEquals("int", mock.useObject(2));
444 assertEquals("Object", mock.useObject(new Object()));
445 assertEquals("byte", mock.useObject((byte) -3));
446 assertEquals("short", mock.useObject((short) 4));
447 assertEquals("long", mock.useObject(-5L));
448 assertEquals("boolean", mock.useObject(true));
449 assertEquals("boolean", mock.useObject(false));
450 assertEquals("char", mock.useObject('A'));
451 assertEquals("float", mock.useObject(-1.5F));
452 assertEquals("double", mock.useObject(23.456));
453 }
454
455
456
457
458 @Test
459 void recordExpectationsUsingTheWithAnyMethodForParameterOfTypeObject() {
460 new Expectations() {
461 {
462 mock.useObject(withAny("a"));
463 result = "String";
464 mock.useObject(withAny(2));
465 result = "int";
466 mock.useObject(withAny((byte) 3));
467 result = "byte";
468 mock.useObject(withAny((short) 4));
469 result = "short";
470 mock.useObject(withAny(5L));
471 result = "long";
472 mock.useObject(withAny(true));
473 result = "boolean";
474 mock.useObject(withAny('\0'));
475 result = "char";
476 mock.useObject(withAny(0.41F));
477 result = "float";
478 mock.useObject(withAny(0.41));
479 result = "double";
480 mock.useObject(withAny(new Object()));
481 result = "Object";
482 }
483 };
484
485 assertInvocationsWithArgumentsOfDifferentTypesToMethodAcceptingAnyObject();
486 }
487
488
489
490
491 @Test
492 void declareFieldInExpectationBlockWithNameHavingSamePrefixAsArgumentMatchingField() {
493 new Expectations() {
494 final Integer anyValue = 1;
495
496 {
497 mock.setValue(anyValue);
498 }
499 };
500
501 mock.setValue(1);
502 }
503
504
505
506
507 @Test
508 void declareMethodInExpectationBlockWithNameHavingSamePrefixAsArgumentMatchingMethod() {
509 final List<Integer> values = new ArrayList<>();
510
511 new Expectations() {
512 {
513 mock.setValues(withEqual('c'), anyBoolean);
514 mock.setValue(withCapture(values));
515 }
516
517 char withEqual(char c) {
518 return c;
519 }
520 };
521
522 mock.setValues('c', true);
523 final Collaborator col = new Collaborator();
524 col.setValue(1);
525
526 assertEquals(singletonList(1), values);
527
528 new Verifications() {
529 {
530 int i;
531 mock.setValue(i = withCapture());
532 assertEquals(1, i);
533
534 List<Collaborator> collaborators = withCapture(new Collaborator());
535 assertSame(col, collaborators.get(0));
536 }
537 };
538 }
539
540
541
542
543
544
545
546
547
548
549 @Test
550 @ExpectedException(MissingInvocation.class)
551 void expectInvocationWithSameMockInstanceButReplayWithNull(
552
553
554 @Mocked final Certificate cert) {
555 new Expectations() {
556 {
557 mock.setValue(withSameInstance(cert));
558 times = 1;
559 }
560 };
561
562 mock.setValue((Certificate) null);
563 }
564
565
566
567
568 @Test
569 @ExpectedException(MissingInvocation.class)
570 void expectInvocationWithMatcherWhichInvokesMockedMethod() {
571 new Expectations() {
572 {
573 mock.setValue(with(new Delegate<Integer>() {
574 @Mock
575 boolean validateAsPositive(int value) {
576
577 mock.simpleOperation(1, "b", null);
578 return value > 0;
579 }
580 }));
581 }
582 };
583
584 mock.setValue(-3);
585 }
586
587
588
589
590
591
592
593 static class ReusableMatcher implements Delegate<Integer> {
594
595
596
597
598
599
600
601
602
603 @Mock
604 final boolean isPositive(int i) {
605 return i > 0;
606 }
607 }
608
609
610
611
612 @Test
613 void extendingAReusableArgumentMatcher() {
614 mock.setValue(5);
615 mock.setValue(123);
616
617 new Verifications() {
618 {
619 mock.setValue(with(new ReusableMatcher() {
620 }));
621 times = 2;
622 }
623 };
624 }
625 }