1<?php
2/*
3 * This file is part of the PHPUnit_MockObject package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11class Framework_MockObjectTest extends PHPUnit_Framework_TestCase
12{
13    public function testMockedMethodIsNeverCalled()
14    {
15        $mock = $this->getMockBuilder(AnInterface::class)
16                     ->getMock();
17
18        $mock->expects($this->never())
19             ->method('doSomething');
20    }
21
22    public function testMockedMethodIsNeverCalledWithParameter()
23    {
24        $mock = $this->getMockBuilder(SomeClass::class)
25                     ->getMock();
26
27        $mock->expects($this->never())
28             ->method('doSomething')
29             ->with('someArg');
30    }
31
32    /**
33     * @doesNotPerformAssertions
34     */
35    public function testMockedMethodIsNotCalledWhenExpectsAnyWithParameter()
36    {
37        $mock = $this->getMockBuilder(SomeClass::class)
38                     ->getMock();
39
40        $mock->expects($this->any())
41             ->method('doSomethingElse')
42             ->with('someArg');
43    }
44
45    /**
46     * @doesNotPerformAssertions
47     */
48    public function testMockedMethodIsNotCalledWhenMethodSpecifiedDirectlyWithParameter()
49    {
50        $mock = $this->getMockBuilder(SomeClass::class)
51                     ->getMock();
52
53        $mock->method('doSomethingElse')
54             ->with('someArg');
55    }
56
57    public function testMockedMethodIsCalledAtLeastOnce()
58    {
59        $mock = $this->getMockBuilder(AnInterface::class)
60                     ->getMock();
61
62        $mock->expects($this->atLeastOnce())
63             ->method('doSomething');
64
65        $mock->doSomething();
66    }
67
68    public function testMockedMethodIsCalledAtLeastOnce2()
69    {
70        $mock = $this->getMockBuilder(AnInterface::class)
71                     ->getMock();
72
73        $mock->expects($this->atLeastOnce())
74             ->method('doSomething');
75
76        $mock->doSomething();
77        $mock->doSomething();
78    }
79
80    public function testMockedMethodIsCalledAtLeastTwice()
81    {
82        $mock = $this->getMockBuilder(AnInterface::class)
83                     ->getMock();
84
85        $mock->expects($this->atLeast(2))
86             ->method('doSomething');
87
88        $mock->doSomething();
89        $mock->doSomething();
90    }
91
92    public function testMockedMethodIsCalledAtLeastTwice2()
93    {
94        $mock = $this->getMockBuilder(AnInterface::class)
95                     ->getMock();
96
97        $mock->expects($this->atLeast(2))
98             ->method('doSomething');
99
100        $mock->doSomething();
101        $mock->doSomething();
102        $mock->doSomething();
103    }
104
105    public function testMockedMethodIsCalledAtMostTwice()
106    {
107        $mock = $this->getMockBuilder(AnInterface::class)
108                     ->getMock();
109
110        $mock->expects($this->atMost(2))
111             ->method('doSomething');
112
113        $mock->doSomething();
114        $mock->doSomething();
115    }
116
117    public function testMockedMethodIsCalledAtMosttTwice2()
118    {
119        $mock = $this->getMockBuilder(AnInterface::class)
120                     ->getMock();
121
122        $mock->expects($this->atMost(2))
123             ->method('doSomething');
124
125        $mock->doSomething();
126    }
127
128    public function testMockedMethodIsCalledOnce()
129    {
130        $mock = $this->getMockBuilder(AnInterface::class)
131                     ->getMock();
132
133        $mock->expects($this->once())
134             ->method('doSomething');
135
136        $mock->doSomething();
137    }
138
139    public function testMockedMethodIsCalledOnceWithParameter()
140    {
141        $mock = $this->getMockBuilder(SomeClass::class)
142                     ->getMock();
143
144        $mock->expects($this->once())
145             ->method('doSomethingElse')
146             ->with($this->equalTo('something'));
147
148        $mock->doSomethingElse('something');
149    }
150
151    public function testMockedMethodIsCalledExactly()
152    {
153        $mock = $this->getMockBuilder(AnInterface::class)
154                     ->getMock();
155
156        $mock->expects($this->exactly(2))
157             ->method('doSomething');
158
159        $mock->doSomething();
160        $mock->doSomething();
161    }
162
163    public function testStubbedException()
164    {
165        $mock = $this->getMockBuilder(AnInterface::class)
166                     ->getMock();
167
168        $mock->expects($this->any())
169             ->method('doSomething')
170             ->will($this->throwException(new Exception));
171
172        $this->expectException(Exception::class);
173
174        $mock->doSomething();
175    }
176
177    public function testStubbedWillThrowException()
178    {
179        $mock = $this->getMockBuilder(AnInterface::class)
180                     ->getMock();
181
182        $mock->expects($this->any())
183             ->method('doSomething')
184             ->willThrowException(new Exception);
185
186        $this->expectException(Exception::class);
187
188        $mock->doSomething();
189    }
190
191    public function testStubbedReturnValue()
192    {
193        $mock = $this->getMockBuilder(AnInterface::class)
194                     ->getMock();
195
196        $mock->expects($this->any())
197             ->method('doSomething')
198             ->will($this->returnValue('something'));
199
200        $this->assertEquals('something', $mock->doSomething());
201
202        $mock = $this->getMockBuilder(AnInterface::class)
203                     ->getMock();
204
205        $mock->expects($this->any())
206             ->method('doSomething')
207             ->willReturn('something');
208
209        $this->assertEquals('something', $mock->doSomething());
210    }
211
212    public function testStubbedReturnValueMap()
213    {
214        $map = [
215            ['a', 'b', 'c', 'd'],
216            ['e', 'f', 'g', 'h']
217        ];
218
219        $mock = $this->getMockBuilder(AnInterface::class)
220                     ->getMock();
221
222        $mock->expects($this->any())
223             ->method('doSomething')
224             ->will($this->returnValueMap($map));
225
226        $this->assertEquals('d', $mock->doSomething('a', 'b', 'c'));
227        $this->assertEquals('h', $mock->doSomething('e', 'f', 'g'));
228        $this->assertEquals(null, $mock->doSomething('foo', 'bar'));
229
230        $mock = $this->getMockBuilder(AnInterface::class)
231                     ->getMock();
232
233        $mock->expects($this->any())
234             ->method('doSomething')
235             ->willReturnMap($map);
236
237        $this->assertEquals('d', $mock->doSomething('a', 'b', 'c'));
238        $this->assertEquals('h', $mock->doSomething('e', 'f', 'g'));
239        $this->assertEquals(null, $mock->doSomething('foo', 'bar'));
240    }
241
242    public function testStubbedReturnArgument()
243    {
244        $mock = $this->getMockBuilder(AnInterface::class)
245                     ->getMock();
246
247        $mock->expects($this->any())
248             ->method('doSomething')
249             ->will($this->returnArgument(1));
250
251        $this->assertEquals('b', $mock->doSomething('a', 'b'));
252
253        $mock = $this->getMockBuilder(AnInterface::class)
254                     ->getMock();
255
256        $mock->expects($this->any())
257             ->method('doSomething')
258             ->willReturnArgument(1);
259
260        $this->assertEquals('b', $mock->doSomething('a', 'b'));
261    }
262
263    public function testFunctionCallback()
264    {
265        $mock = $this->getMockBuilder(SomeClass::class)
266                     ->setMethods(['doSomething'])
267                     ->getMock();
268
269        $mock->expects($this->once())
270             ->method('doSomething')
271             ->will($this->returnCallback('functionCallback'));
272
273        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
274
275        $mock = $this->getMockBuilder(SomeClass::class)
276                     ->setMethods(['doSomething'])
277                     ->getMock();
278
279        $mock->expects($this->once())
280             ->method('doSomething')
281             ->willReturnCallback('functionCallback');
282
283        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
284    }
285
286    public function testStubbedReturnSelf()
287    {
288        $mock = $this->getMockBuilder(AnInterface::class)
289                     ->getMock();
290
291        $mock->expects($this->any())
292             ->method('doSomething')
293             ->will($this->returnSelf());
294
295        $this->assertEquals($mock, $mock->doSomething());
296
297        $mock = $this->getMockBuilder(AnInterface::class)
298                     ->getMock();
299
300        $mock->expects($this->any())
301             ->method('doSomething')
302             ->willReturnSelf();
303
304        $this->assertEquals($mock, $mock->doSomething());
305    }
306
307    public function testStubbedReturnOnConsecutiveCalls()
308    {
309        $mock = $this->getMockBuilder(AnInterface::class)
310                     ->getMock();
311
312        $mock->expects($this->any())
313             ->method('doSomething')
314             ->will($this->onConsecutiveCalls('a', 'b', 'c'));
315
316        $this->assertEquals('a', $mock->doSomething());
317        $this->assertEquals('b', $mock->doSomething());
318        $this->assertEquals('c', $mock->doSomething());
319
320        $mock = $this->getMockBuilder(AnInterface::class)
321                     ->getMock();
322
323        $mock->expects($this->any())
324             ->method('doSomething')
325             ->willReturnOnConsecutiveCalls('a', 'b', 'c');
326
327        $this->assertEquals('a', $mock->doSomething());
328        $this->assertEquals('b', $mock->doSomething());
329        $this->assertEquals('c', $mock->doSomething());
330    }
331
332    public function testStaticMethodCallback()
333    {
334        $mock = $this->getMockBuilder(SomeClass::class)
335                     ->setMethods(['doSomething'])
336                     ->getMock();
337
338        $mock->expects($this->once())
339             ->method('doSomething')
340             ->will($this->returnCallback(['MethodCallback', 'staticCallback']));
341
342        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
343    }
344
345    public function testPublicMethodCallback()
346    {
347        $mock = $this->getMockBuilder(SomeClass::class)
348                     ->setMethods(['doSomething'])
349                     ->getMock();
350
351        $mock->expects($this->once())
352             ->method('doSomething')
353             ->will($this->returnCallback([new MethodCallback, 'nonStaticCallback']));
354
355        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
356    }
357
358    public function testMockClassOnlyGeneratedOnce()
359    {
360        $mock1 = $this->getMockBuilder(AnInterface::class)
361                     ->getMock();
362
363        $mock2 = $this->getMockBuilder(AnInterface::class)
364                     ->getMock();
365
366        $this->assertEquals(get_class($mock1), get_class($mock2));
367    }
368
369    public function testMockClassDifferentForPartialMocks()
370    {
371        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
372                      ->getMock();
373
374        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
375                      ->setMethods(['doSomething'])
376                      ->getMock();
377
378        $mock3 = $this->getMockBuilder(PartialMockTestClass::class)
379                      ->setMethods(['doSomething'])
380                      ->getMock();
381
382        $mock4 = $this->getMockBuilder(PartialMockTestClass::class)
383                      ->setMethods(['doAnotherThing'])
384                      ->getMock();
385
386        $mock5 = $this->getMockBuilder(PartialMockTestClass::class)
387                      ->setMethods(['doAnotherThing'])
388                      ->getMock();
389
390        $this->assertNotEquals(get_class($mock1), get_class($mock2));
391        $this->assertNotEquals(get_class($mock1), get_class($mock3));
392        $this->assertNotEquals(get_class($mock1), get_class($mock4));
393        $this->assertNotEquals(get_class($mock1), get_class($mock5));
394        $this->assertEquals(get_class($mock2), get_class($mock3));
395        $this->assertNotEquals(get_class($mock2), get_class($mock4));
396        $this->assertNotEquals(get_class($mock2), get_class($mock5));
397        $this->assertEquals(get_class($mock4), get_class($mock5));
398    }
399
400    public function testMockClassStoreOverrulable()
401    {
402        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
403                      ->getMock();
404
405        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
406                      ->setMockClassName('MyMockClassNameForPartialMockTestClass1')
407                      ->getMock();
408
409        $mock3 = $this->getMockBuilder(PartialMockTestClass::class)
410                      ->getMock();
411
412        $mock4 = $this->getMockBuilder(PartialMockTestClass::class)
413                      ->setMethods(['doSomething'])
414                      ->setMockClassName('AnotherMockClassNameForPartialMockTestClass')
415                      ->getMock();
416
417        $mock5 = $this->getMockBuilder(PartialMockTestClass::class)
418                      ->setMockClassName('MyMockClassNameForPartialMockTestClass2')
419                      ->getMock();
420
421        $this->assertNotEquals(get_class($mock1), get_class($mock2));
422        $this->assertEquals(get_class($mock1), get_class($mock3));
423        $this->assertNotEquals(get_class($mock1), get_class($mock4));
424        $this->assertNotEquals(get_class($mock2), get_class($mock3));
425        $this->assertNotEquals(get_class($mock2), get_class($mock4));
426        $this->assertNotEquals(get_class($mock2), get_class($mock5));
427        $this->assertNotEquals(get_class($mock3), get_class($mock4));
428        $this->assertNotEquals(get_class($mock3), get_class($mock5));
429        $this->assertNotEquals(get_class($mock4), get_class($mock5));
430    }
431
432    public function testGetMockWithFixedClassNameCanProduceTheSameMockTwice()
433    {
434        $mock = $this->getMockBuilder(stdClass::class)->setMockClassName('FixedName')->getMock();
435        $mock = $this->getMockBuilder(stdClass::class)->setMockClassName('FixedName')->getMock();
436        $this->assertInstanceOf(stdClass::class, $mock);
437    }
438
439    public function testOriginalConstructorSettingConsidered()
440    {
441        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
442                      ->getMock();
443
444        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
445                      ->disableOriginalConstructor()
446                      ->getMock();
447
448        $this->assertTrue($mock1->constructorCalled);
449        $this->assertFalse($mock2->constructorCalled);
450    }
451
452    public function testOriginalCloneSettingConsidered()
453    {
454        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
455                      ->getMock();
456
457        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
458                      ->disableOriginalClone()
459                      ->getMock();
460
461        $this->assertNotEquals(get_class($mock1), get_class($mock2));
462    }
463
464    public function testGetMockForAbstractClass()
465    {
466        $mock = $this->getMockBuilder(AbstractMockTestClass::class)
467                     ->getMock();
468
469        $mock->expects($this->never())
470             ->method('doSomething');
471    }
472
473    /**
474     * @dataProvider traversableProvider
475     */
476    public function testGetMockForTraversable($type)
477    {
478        $mock = $this->getMockBuilder($type)
479                     ->getMock();
480
481        $this->assertInstanceOf(Traversable::class, $mock);
482    }
483
484    public function testMultipleInterfacesCanBeMockedInSingleObject()
485    {
486        $mock = $this->getMockBuilder([AnInterface::class, AnotherInterface::class])
487                     ->getMock();
488
489        $this->assertInstanceOf(AnInterface::class, $mock);
490        $this->assertInstanceOf(AnotherInterface::class, $mock);
491    }
492
493    public function testGetMockForTrait()
494    {
495        $mock = $this->getMockForTrait(AbstractTrait::class);
496
497        $mock->expects($this->never())
498             ->method('doSomething');
499
500        $parent = get_parent_class($mock);
501        $traits = class_uses($parent, false);
502
503        $this->assertContains(AbstractTrait::class, $traits);
504    }
505
506    public function testClonedMockObjectShouldStillEqualTheOriginal()
507    {
508        $a = $this->getMockBuilder(stdClass::class)
509                  ->getMock();
510
511        $b = clone $a;
512
513        $this->assertEquals($a, $b);
514    }
515
516    public function testMockObjectsConstructedIndepentantlyShouldBeEqual()
517    {
518        $a = $this->getMockBuilder(stdClass::class)
519                  ->getMock();
520
521        $b = $this->getMockBuilder(stdClass::class)
522                  ->getMock();
523
524        $this->assertEquals($a, $b);
525    }
526
527    public function testMockObjectsConstructedIndepentantlyShouldNotBeTheSame()
528    {
529        $a = $this->getMockBuilder(stdClass::class)
530                  ->getMock();
531
532        $b = $this->getMockBuilder(stdClass::class)
533                  ->getMock();
534
535        $this->assertNotSame($a, $b);
536    }
537
538    public function testClonedMockObjectCanBeUsedInPlaceOfOriginalOne()
539    {
540        $x = $this->getMockBuilder(stdClass::class)
541                  ->getMock();
542
543        $y = clone $x;
544
545        $mock = $this->getMockBuilder(stdClass::class)
546                     ->setMethods(['foo'])
547                     ->getMock();
548
549        $mock->expects($this->once())
550             ->method('foo')
551             ->with($this->equalTo($x));
552
553        $mock->foo($y);
554    }
555
556    public function testClonedMockObjectIsNotIdenticalToOriginalOne()
557    {
558        $x = $this->getMockBuilder(stdClass::class)
559                  ->getMock();
560
561        $y = clone $x;
562
563        $mock = $this->getMockBuilder(stdClass::class)
564                     ->setMethods(['foo'])
565                     ->getMock();
566
567        $mock->expects($this->once())
568             ->method('foo')
569             ->with($this->logicalNot($this->identicalTo($x)));
570
571        $mock->foo($y);
572    }
573
574    public function testObjectMethodCallWithArgumentCloningEnabled()
575    {
576        $expectedObject = new stdClass;
577
578        $mock = $this->getMockBuilder('SomeClass')
579                     ->setMethods(['doSomethingElse'])
580                     ->enableArgumentCloning()
581                     ->getMock();
582
583        $actualArguments = [];
584
585        $mock->expects($this->any())
586             ->method('doSomethingElse')
587             ->will(
588                 $this->returnCallback(
589                     function () use (&$actualArguments) {
590                         $actualArguments = func_get_args();
591                     }
592                 )
593             );
594
595        $mock->doSomethingElse($expectedObject);
596
597        $this->assertEquals(1, count($actualArguments));
598        $this->assertEquals($expectedObject, $actualArguments[0]);
599        $this->assertNotSame($expectedObject, $actualArguments[0]);
600    }
601
602    public function testObjectMethodCallWithArgumentCloningDisabled()
603    {
604        $expectedObject = new stdClass;
605
606        $mock = $this->getMockBuilder('SomeClass')
607                     ->setMethods(['doSomethingElse'])
608                     ->disableArgumentCloning()
609                     ->getMock();
610
611        $actualArguments = [];
612
613        $mock->expects($this->any())
614             ->method('doSomethingElse')
615             ->will(
616                 $this->returnCallback(
617                     function () use (&$actualArguments) {
618                         $actualArguments = func_get_args();
619                     }
620                 )
621             );
622
623        $mock->doSomethingElse($expectedObject);
624
625        $this->assertEquals(1, count($actualArguments));
626        $this->assertSame($expectedObject, $actualArguments[0]);
627    }
628
629    public function testArgumentCloningOptionGeneratesUniqueMock()
630    {
631        $mockWithCloning = $this->getMockBuilder('SomeClass')
632                                ->setMethods(['doSomethingElse'])
633                                ->enableArgumentCloning()
634                                ->getMock();
635
636        $mockWithoutCloning = $this->getMockBuilder('SomeClass')
637                                   ->setMethods(['doSomethingElse'])
638                                   ->disableArgumentCloning()
639                                   ->getMock();
640
641        $this->assertNotEquals($mockWithCloning, $mockWithoutCloning);
642    }
643
644    public function testVerificationOfMethodNameFailsWithoutParameters()
645    {
646        $mock = $this->getMockBuilder(SomeClass::class)
647                     ->setMethods(['right', 'wrong'])
648                     ->getMock();
649
650        $mock->expects($this->once())
651             ->method('right');
652
653        $mock->wrong();
654
655        try {
656            $mock->__phpunit_verify();
657            $this->fail('Expected exception');
658        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
659            $this->assertSame(
660                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s).\n"
661                . "Method was expected to be called 1 times, actually called 0 times.\n",
662                $e->getMessage()
663            );
664        }
665
666        $this->resetMockObjects();
667    }
668
669    public function testVerificationOfMethodNameFailsWithParameters()
670    {
671        $mock = $this->getMockBuilder(SomeClass::class)
672                     ->setMethods(['right', 'wrong'])
673                     ->getMock();
674
675        $mock->expects($this->once())
676             ->method('right');
677
678        $mock->wrong();
679
680        try {
681            $mock->__phpunit_verify();
682            $this->fail('Expected exception');
683        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
684            $this->assertSame(
685                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s).\n"
686                . "Method was expected to be called 1 times, actually called 0 times.\n",
687                $e->getMessage()
688            );
689        }
690
691        $this->resetMockObjects();
692    }
693
694    public function testVerificationOfMethodNameFailsWithWrongParameters()
695    {
696        $mock = $this->getMockBuilder(SomeClass::class)
697                     ->setMethods(['right', 'wrong'])
698                     ->getMock();
699
700        $mock->expects($this->once())
701             ->method('right')
702             ->with(['first', 'second']);
703
704        try {
705            $mock->right(['second']);
706        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
707            $this->assertSame(
708                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s)\n"
709                . "Parameter 0 for invocation SomeClass::right(Array (...)) does not match expected value.\n"
710                . 'Failed asserting that two arrays are equal.',
711                $e->getMessage()
712            );
713        }
714
715        try {
716            $mock->__phpunit_verify();
717            $this->fail('Expected exception');
718        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
719            $this->assertSame(
720                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s).\n"
721                . "Parameter 0 for invocation SomeClass::right(Array (...)) does not match expected value.\n"
722                . "Failed asserting that two arrays are equal.\n"
723                . "--- Expected\n"
724                . "+++ Actual\n"
725                . "@@ @@\n"
726                . " Array (\n"
727                . "-    0 => 'first'\n"
728                . "-    1 => 'second'\n"
729                . "+    0 => 'second'\n"
730                . " )\n",
731                $e->getMessage()
732            );
733        }
734
735        $this->resetMockObjects();
736    }
737
738    public function testVerificationOfNeverFailsWithEmptyParameters()
739    {
740        $mock = $this->getMockBuilder(SomeClass::class)
741                     ->setMethods(['right', 'wrong'])
742                     ->getMock();
743
744        $mock->expects($this->never())
745             ->method('right')
746             ->with();
747
748        try {
749            $mock->right();
750            $this->fail('Expected exception');
751        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
752            $this->assertSame(
753                'SomeClass::right() was not expected to be called.',
754                $e->getMessage()
755            );
756        }
757
758        $this->resetMockObjects();
759    }
760
761    public function testVerificationOfNeverFailsWithAnyParameters()
762    {
763        $mock = $this->getMockBuilder(SomeClass::class)
764                     ->setMethods(['right', 'wrong'])
765                     ->getMock();
766
767        $mock->expects($this->never())
768             ->method('right')
769             ->withAnyParameters();
770
771        try {
772            $mock->right();
773            $this->fail('Expected exception');
774        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
775            $this->assertSame(
776                'SomeClass::right() was not expected to be called.',
777                $e->getMessage()
778            );
779        }
780
781        $this->resetMockObjects();
782    }
783
784    public function testWithAnythingInsteadOfWithAnyParameters()
785    {
786        $mock = $this->getMockBuilder(SomeClass::class)
787                     ->setMethods(['right', 'wrong'])
788                     ->getMock();
789
790        $mock->expects($this->once())
791             ->method('right')
792             ->with($this->anything());
793
794        try {
795            $mock->right();
796            $this->fail('Expected exception');
797        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
798            $this->assertSame(
799                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s)\n" .
800                "Parameter count for invocation SomeClass::right() is too low.\n" .
801                'To allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead.',
802                $e->getMessage()
803            );
804        }
805
806        $this->resetMockObjects();
807    }
808
809    /**
810     * See https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81
811     */
812    public function testMockArgumentsPassedByReference()
813    {
814        $foo = $this->getMockBuilder('MethodCallbackByReference')
815                    ->setMethods(['bar'])
816                    ->disableOriginalConstructor()
817                    ->disableArgumentCloning()
818                    ->getMock();
819
820        $foo->expects($this->any())
821            ->method('bar')
822            ->will($this->returnCallback([$foo, 'callback']));
823
824        $a = $b = $c = 0;
825
826        $foo->bar($a, $b, $c);
827
828        $this->assertEquals(1, $b);
829    }
830
831    /**
832     * See https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81
833     */
834    public function testMockArgumentsPassedByReference2()
835    {
836        $foo = $this->getMockBuilder('MethodCallbackByReference')
837                    ->disableOriginalConstructor()
838                    ->disableArgumentCloning()
839                    ->getMock();
840
841        $foo->expects($this->any())
842            ->method('bar')
843            ->will($this->returnCallback(
844                function (&$a, &$b, $c) {
845                    $b = 1;
846                }
847            ));
848
849        $a = $b = $c = 0;
850
851        $foo->bar($a, $b, $c);
852
853        $this->assertEquals(1, $b);
854    }
855
856    /**
857     * @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/116
858     */
859    public function testMockArgumentsPassedByReference3()
860    {
861        $foo = $this->getMockBuilder('MethodCallbackByReference')
862                    ->setMethods(['bar'])
863                    ->disableOriginalConstructor()
864                    ->disableArgumentCloning()
865                    ->getMock();
866
867        $a = new stdClass;
868        $b = $c = 0;
869
870        $foo->expects($this->any())
871            ->method('bar')
872            ->with($a, $b, $c)
873            ->will($this->returnCallback([$foo, 'callback']));
874
875        $this->assertNull($foo->bar($a, $b, $c));
876    }
877
878    /**
879     * @see https://github.com/sebastianbergmann/phpunit/issues/796
880     */
881    public function testMockArgumentsPassedByReference4()
882    {
883        $foo = $this->getMockBuilder('MethodCallbackByReference')
884                    ->setMethods(['bar'])
885                    ->disableOriginalConstructor()
886                    ->disableArgumentCloning()
887                    ->getMock();
888
889        $a = new stdClass;
890        $b = $c = 0;
891
892        $foo->expects($this->any())
893            ->method('bar')
894            ->with($this->isInstanceOf(stdClass::class), $b, $c)
895            ->will($this->returnCallback([$foo, 'callback']));
896
897        $this->assertNull($foo->bar($a, $b, $c));
898    }
899
900    /**
901     * @requires extension soap
902     */
903    public function testCreateMockFromWsdl()
904    {
905        $mock = $this->getMockFromWsdl(__DIR__ . '/_fixture/GoogleSearch.wsdl', 'WsdlMock');
906
907        $this->assertStringStartsWith(
908            'Mock_WsdlMock_',
909            get_class($mock)
910        );
911    }
912
913    /**
914     * @requires extension soap
915     */
916    public function testCreateNamespacedMockFromWsdl()
917    {
918        $mock = $this->getMockFromWsdl(__DIR__ . '/_fixture/GoogleSearch.wsdl', 'My\\Space\\WsdlMock');
919
920        $this->assertStringStartsWith(
921            'Mock_WsdlMock_',
922            get_class($mock)
923        );
924    }
925
926    /**
927     * @requires extension soap
928     */
929    public function testCreateTwoMocksOfOneWsdlFile()
930    {
931        $a = $this->getMockFromWsdl(__DIR__ . '/_fixture/GoogleSearch.wsdl');
932        $b = $this->getMockFromWsdl(__DIR__ . '/_fixture/GoogleSearch.wsdl');
933
934        $this->assertStringStartsWith('Mock_GoogleSearch_', get_class($a));
935        $this->assertEquals(get_class($a), get_class($b));
936    }
937
938    /**
939     * @see    https://github.com/sebastianbergmann/phpunit-mock-objects/issues/156
940     * @ticket 156
941     */
942    public function testInterfaceWithStaticMethodCanBeStubbed()
943    {
944        $this->assertInstanceOf(
945            InterfaceWithStaticMethod::class,
946            $this->getMockBuilder(InterfaceWithStaticMethod::class)->getMock()
947        );
948    }
949
950    /**
951     * @expectedException PHPUnit_Framework_MockObject_BadMethodCallException
952     */
953    public function testInvokingStubbedStaticMethodRaisesException()
954    {
955        $mock = $this->getMockBuilder(ClassWithStaticMethod::class)->getMock();
956
957        $mock->staticMethod();
958    }
959
960    /**
961     * @see    https://github.com/sebastianbergmann/phpunit-mock-objects/issues/171
962     * @ticket 171
963     */
964    public function testStubForClassThatImplementsSerializableCanBeCreatedWithoutInvokingTheConstructor()
965    {
966        $this->assertInstanceOf(
967            ClassThatImplementsSerializable::class,
968            $this->getMockBuilder(ClassThatImplementsSerializable::class)
969                 ->disableOriginalConstructor()
970                 ->getMock()
971        );
972    }
973
974    public function testGetMockForClassWithSelfTypeHint()
975    {
976        $this->assertInstanceOf(
977            ClassWithSelfTypeHint::class,
978            $this->getMockBuilder(ClassWithSelfTypeHint::class)->getMock()
979        );
980    }
981
982    private function resetMockObjects()
983    {
984        $refl = new ReflectionObject($this);
985        $refl = $refl->getParentClass();
986        $prop = $refl->getProperty('mockObjects');
987        $prop->setAccessible(true);
988        $prop->setValue($this, []);
989    }
990
991    public function testStringableClassDoesNotThrow()
992    {
993        $mock = $this->getMockBuilder(StringableClass::class)->getMock();
994
995        $this->assertInternalType('string', (string) $mock);
996    }
997
998    public function testStringableClassCanBeMocked()
999    {
1000        $mock = $this->getMockBuilder(StringableClass::class)->getMock();
1001
1002        $mock->method('__toString')->willReturn('foo');
1003
1004        $this->assertSame('foo', (string) $mock);
1005    }
1006
1007    public function traversableProvider()
1008    {
1009        return [
1010          ['Traversable'],
1011          ['\Traversable'],
1012          ['TraversableMockTestInterface'],
1013          [['Traversable']],
1014          [['Iterator','Traversable']],
1015          [['\Iterator','\Traversable']]
1016        ];
1017    }
1018
1019    public function testParameterCallbackConstraintOnlyEvaluatedOnce()
1020    {
1021        $mock                  = $this->getMockBuilder(Foo::class)->setMethods(['bar'])->getMock();
1022        $expectedNumberOfCalls = 1;
1023        $callCount             = 0;
1024
1025        $mock->expects($this->exactly($expectedNumberOfCalls))->method('bar')
1026            ->with($this->callback(function ($argument) use (&$callCount) {
1027                return $argument === 'call_' . $callCount++;
1028            }));
1029
1030        for ($i = 0; $i < $expectedNumberOfCalls; $i++) {
1031            $mock->bar('call_' . $i);
1032        }
1033    }
1034}
1035