MockObjectTest   F
last analyzed

Complexity

Total Complexity 80

Size/Duplication

Total Lines 1119
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 580
dl 0
loc 1119
rs 2
c 0
b 0
f 0
wmc 80

71 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetMockForAbstractClass() 0 7 1
A testStubbedWillThrowException() 0 12 1
A testClonedMockObjectCanBeUsedInPlaceOfOriginalOne() 0 16 1
A testVerificationOfNeverFailsWithEmptyParameters() 0 21 2
A testMockClassStoreOverrulable() 0 30 1
A testMockedMethodIsCalledOnce() 0 9 1
A testInterfaceWithStaticMethodCanBeStubbed() 0 5 1
A testInvokingStubbedStaticMethodRaisesException() 0 7 1
A testStringableClassCanBeMocked() 0 8 1
A testMockedMethodIsCalledAtMosttTwice2() 0 9 1
A testMockedMethodIsCalledAtLeastTwice() 0 10 1
A testDisableAutomaticReturnValueGeneration() 0 12 1
A testStringableClassDoesNotThrow() 0 6 1
A testOriginalConstructorSettingConsidered() 0 11 1
A testParameterCallbackConstraintOnlyEvaluatedOnce() 0 13 2
A testMockedMethodIsCalledExactly() 0 10 1
A testMockedMethodIsNotCalledWhenExpectsAnyWithParameter() 0 8 1
A testMockedMethodIsNotCalledWhenMethodSpecifiedDirectlyWithParameter() 0 7 1
A testStubbedReturnSelf() 0 19 1
A testStubbedReturnOnConsecutiveCalls() 0 23 1
A testGetMockForClassWithSelfTypeHint() 0 5 1
A testStubForClassThatImplementsSerializableCanBeCreatedWithoutInvokingTheConstructor() 0 7 1
A testMockObjectsConstructedIndepentantlyShouldNotBeTheSame() 0 9 1
A testPublicMethodCallback() 0 11 1
A testMultipleInterfacesCanBeMockedInSingleObject() 0 7 1
A testFunctionCallback() 0 21 1
A testGetMockWithFixedClassNameCanProduceTheSameMockTwice() 0 4 1
A testVerificationOfNeverFailsWithAnyParameters() 0 21 2
A testMockArgumentsPassedByReference3() 0 17 1
A testTraitCanBeDoubled() 0 5 1
A testMockArgumentsPassedByReference2() 0 20 1
A testStubbedReturnArgument() 0 19 1
A testClonedMockObjectShouldStillEqualTheOriginal() 0 8 1
A testCreateTwoMocksOfOneWsdlFile() 0 7 1
A testStubbedException() 0 12 1
A traversableProvider() 0 9 1
A testMockedMethodIsCalledAtLeastOnce2() 0 10 1
A testCreateNamespacedMockFromWsdl() 0 7 1
A testMockArgumentsPassedByReference() 0 17 1
A testClonedMockObjectIsNotIdenticalToOriginalOne() 0 16 1
A testMockedMethodIsNeverCalled() 0 7 1
A testObjectMethodCallWithArgumentCloningEnabled() 0 26 1
A testTraitWithConstructorCanBeDoubled() 0 5 1
A testVerificationOfMethodNameFailsWithParameters() 0 23 2
A testGetMockForTraversable() 0 6 1
A testMockArgumentsPassedByReference4() 0 17 1
A testCreateMockFromWsdl() 0 7 1
A testCreateMockOfWsdlFileWithSpecialChars() 0 5 1
A testGetMockForTrait() 0 11 1
A testMockObjectsConstructedIndepentantlyShouldBeEqual() 0 9 1
A testStubbedReturnValue() 0 19 1
A testMockClassDifferentForPartialMocks() 0 29 1
A testMockClassOnlyGeneratedOnce() 0 9 1
A testStubbedReturnValueMap() 0 28 1
A testReturnTypesAreMockedCorrectly() 0 12 1
A testVerificationOfMethodNameFailsWithoutParameters() 0 23 2
A resetMockObjects() 0 7 1
A testObjectReturnTypeIsMockedCorrectly() 0 6 1
A testMockedMethodIsCalledAtMostTwice() 0 10 1
A testMockedMethodIsNeverCalledWithParameter() 0 8 1
A testMockedMethodIsCalledAtLeastOnce() 0 9 1
A testMockedMethodIsCalledAtLeastTwice2() 0 11 1
A testObjectMethodCallWithArgumentCloningDisabled() 0 25 1
A testWithAnythingInsteadOfWithAnyParameters() 0 23 2
A testDisableAutomaticReturnValueGenerationWithToString() 0 20 2
A testOriginalCloneSettingConsidered() 0 10 1
A testVerificationOfMethodNameFailsWithWrongParameters() 0 44 3
A testMockedMethodIsCalledOnceWithParameter() 0 10 1
A testStaticMethodCallback() 0 11 1
A testVoidReturnTypeIsMockedCorrectly() 0 6 1
A testArgumentCloningOptionGeneratesUniqueMock() 0 13 1

How to fix   Complexity   

Complex Class

Complex classes like MockObjectTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MockObjectTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
use PHPUnit\Framework\ExpectationFailedException;
12
use PHPUnit\Framework\MockObject\MockObject;
13
use PHPUnit\Framework\TestCase;
14
15
class MockObjectTest extends TestCase
16
{
17
    public function testMockedMethodIsNeverCalled(): void
18
    {
19
        $mock = $this->getMockBuilder(AnInterface::class)
20
                     ->getMock();
21
22
        $mock->expects($this->never())
23
             ->method('doSomething');
24
    }
25
26
    public function testMockedMethodIsNeverCalledWithParameter(): void
27
    {
28
        $mock = $this->getMockBuilder(SomeClass::class)
29
                     ->getMock();
30
31
        $mock->expects($this->never())
32
             ->method('doSomething')
33
             ->with('someArg');
34
    }
35
36
    /**
37
     * @doesNotPerformAssertions
38
     */
39
    public function testMockedMethodIsNotCalledWhenExpectsAnyWithParameter(): void
40
    {
41
        $mock = $this->getMockBuilder(SomeClass::class)
42
                     ->getMock();
43
44
        $mock->expects($this->any())
45
             ->method('doSomethingElse')
46
             ->with('someArg');
47
    }
48
49
    /**
50
     * @doesNotPerformAssertions
51
     */
52
    public function testMockedMethodIsNotCalledWhenMethodSpecifiedDirectlyWithParameter(): void
53
    {
54
        $mock = $this->getMockBuilder(SomeClass::class)
55
                     ->getMock();
56
57
        $mock->method('doSomethingElse')
58
             ->with('someArg');
59
    }
60
61
    public function testMockedMethodIsCalledAtLeastOnce(): void
62
    {
63
        $mock = $this->getMockBuilder(AnInterface::class)
64
                     ->getMock();
65
66
        $mock->expects($this->atLeastOnce())
67
             ->method('doSomething');
68
69
        $mock->doSomething();
70
    }
71
72
    public function testMockedMethodIsCalledAtLeastOnce2(): void
73
    {
74
        $mock = $this->getMockBuilder(AnInterface::class)
75
                     ->getMock();
76
77
        $mock->expects($this->atLeastOnce())
78
             ->method('doSomething');
79
80
        $mock->doSomething();
81
        $mock->doSomething();
82
    }
83
84
    public function testMockedMethodIsCalledAtLeastTwice(): void
85
    {
86
        $mock = $this->getMockBuilder(AnInterface::class)
87
                     ->getMock();
88
89
        $mock->expects($this->atLeast(2))
90
             ->method('doSomething');
91
92
        $mock->doSomething();
93
        $mock->doSomething();
94
    }
95
96
    public function testMockedMethodIsCalledAtLeastTwice2(): void
97
    {
98
        $mock = $this->getMockBuilder(AnInterface::class)
99
                     ->getMock();
100
101
        $mock->expects($this->atLeast(2))
102
             ->method('doSomething');
103
104
        $mock->doSomething();
105
        $mock->doSomething();
106
        $mock->doSomething();
107
    }
108
109
    public function testMockedMethodIsCalledAtMostTwice(): void
110
    {
111
        $mock = $this->getMockBuilder(AnInterface::class)
112
                     ->getMock();
113
114
        $mock->expects($this->atMost(2))
115
             ->method('doSomething');
116
117
        $mock->doSomething();
118
        $mock->doSomething();
119
    }
120
121
    public function testMockedMethodIsCalledAtMosttTwice2(): void
122
    {
123
        $mock = $this->getMockBuilder(AnInterface::class)
124
                     ->getMock();
125
126
        $mock->expects($this->atMost(2))
127
             ->method('doSomething');
128
129
        $mock->doSomething();
130
    }
131
132
    public function testMockedMethodIsCalledOnce(): void
133
    {
134
        $mock = $this->getMockBuilder(AnInterface::class)
135
                     ->getMock();
136
137
        $mock->expects($this->once())
138
             ->method('doSomething');
139
140
        $mock->doSomething();
141
    }
142
143
    public function testMockedMethodIsCalledOnceWithParameter(): void
144
    {
145
        $mock = $this->getMockBuilder(SomeClass::class)
146
                     ->getMock();
147
148
        $mock->expects($this->once())
149
             ->method('doSomethingElse')
150
             ->with($this->equalTo('something'));
151
152
        $mock->doSomethingElse('something');
153
    }
154
155
    public function testMockedMethodIsCalledExactly(): void
156
    {
157
        $mock = $this->getMockBuilder(AnInterface::class)
158
                     ->getMock();
159
160
        $mock->expects($this->exactly(2))
161
             ->method('doSomething');
162
163
        $mock->doSomething();
164
        $mock->doSomething();
165
    }
166
167
    public function testStubbedException(): void
168
    {
169
        $mock = $this->getMockBuilder(AnInterface::class)
170
                     ->getMock();
171
172
        $mock->expects($this->any())
173
             ->method('doSomething')
174
             ->will($this->throwException(new \Exception));
175
176
        $this->expectException(\Exception::class);
177
178
        $mock->doSomething();
179
    }
180
181
    public function testStubbedWillThrowException(): void
182
    {
183
        $mock = $this->getMockBuilder(AnInterface::class)
184
                     ->getMock();
185
186
        $mock->expects($this->any())
187
             ->method('doSomething')
188
             ->willThrowException(new \Exception);
189
190
        $this->expectException(\Exception::class);
191
192
        $mock->doSomething();
193
    }
194
195
    public function testStubbedReturnValue(): void
196
    {
197
        $mock = $this->getMockBuilder(AnInterface::class)
198
                     ->getMock();
199
200
        $mock->expects($this->any())
201
             ->method('doSomething')
202
             ->will($this->returnValue('something'));
203
204
        $this->assertEquals('something', $mock->doSomething());
205
206
        $mock = $this->getMockBuilder(AnInterface::class)
207
                     ->getMock();
208
209
        $mock->expects($this->any())
210
             ->method('doSomething')
211
             ->willReturn('something');
212
213
        $this->assertEquals('something', $mock->doSomething());
214
    }
215
216
    public function testStubbedReturnValueMap(): void
217
    {
218
        $map = [
219
            ['a', 'b', 'c', 'd'],
220
            ['e', 'f', 'g', 'h'],
221
        ];
222
223
        $mock = $this->getMockBuilder(AnInterface::class)
224
                     ->getMock();
225
226
        $mock->expects($this->any())
227
             ->method('doSomething')
228
             ->will($this->returnValueMap($map));
229
230
        $this->assertEquals('d', $mock->doSomething('a', 'b', 'c'));
231
        $this->assertEquals('h', $mock->doSomething('e', 'f', 'g'));
232
        $this->assertNull($mock->doSomething('foo', 'bar'));
233
234
        $mock = $this->getMockBuilder(AnInterface::class)
235
                     ->getMock();
236
237
        $mock->expects($this->any())
238
             ->method('doSomething')
239
             ->willReturnMap($map);
240
241
        $this->assertEquals('d', $mock->doSomething('a', 'b', 'c'));
242
        $this->assertEquals('h', $mock->doSomething('e', 'f', 'g'));
243
        $this->assertNull($mock->doSomething('foo', 'bar'));
244
    }
245
246
    public function testStubbedReturnArgument(): void
247
    {
248
        $mock = $this->getMockBuilder(AnInterface::class)
249
                     ->getMock();
250
251
        $mock->expects($this->any())
252
             ->method('doSomething')
253
             ->will($this->returnArgument(1));
254
255
        $this->assertEquals('b', $mock->doSomething('a', 'b'));
256
257
        $mock = $this->getMockBuilder(AnInterface::class)
258
                     ->getMock();
259
260
        $mock->expects($this->any())
261
             ->method('doSomething')
262
             ->willReturnArgument(1);
263
264
        $this->assertEquals('b', $mock->doSomething('a', 'b'));
265
    }
266
267
    public function testFunctionCallback(): void
268
    {
269
        $mock = $this->getMockBuilder(SomeClass::class)
270
                     ->setMethods(['doSomething'])
271
                     ->getMock();
272
273
        $mock->expects($this->once())
274
             ->method('doSomething')
275
             ->will($this->returnCallback('FunctionCallbackWrapper::functionCallback'));
276
277
        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
278
279
        $mock = $this->getMockBuilder(SomeClass::class)
280
                     ->setMethods(['doSomething'])
281
                     ->getMock();
282
283
        $mock->expects($this->once())
284
             ->method('doSomething')
285
             ->willReturnCallback('FunctionCallbackWrapper::functionCallback');
286
287
        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
288
    }
289
290
    public function testStubbedReturnSelf(): void
291
    {
292
        $mock = $this->getMockBuilder(AnInterface::class)
293
                     ->getMock();
294
295
        $mock->expects($this->any())
296
             ->method('doSomething')
297
             ->will($this->returnSelf());
298
299
        $this->assertEquals($mock, $mock->doSomething());
300
301
        $mock = $this->getMockBuilder(AnInterface::class)
302
                     ->getMock();
303
304
        $mock->expects($this->any())
305
             ->method('doSomething')
306
             ->willReturnSelf();
307
308
        $this->assertEquals($mock, $mock->doSomething());
309
    }
310
311
    public function testStubbedReturnOnConsecutiveCalls(): void
312
    {
313
        $mock = $this->getMockBuilder(AnInterface::class)
314
                     ->getMock();
315
316
        $mock->expects($this->any())
317
             ->method('doSomething')
318
             ->will($this->onConsecutiveCalls('a', 'b', 'c'));
319
320
        $this->assertEquals('a', $mock->doSomething());
321
        $this->assertEquals('b', $mock->doSomething());
322
        $this->assertEquals('c', $mock->doSomething());
323
324
        $mock = $this->getMockBuilder(AnInterface::class)
325
                     ->getMock();
326
327
        $mock->expects($this->any())
328
             ->method('doSomething')
329
             ->willReturnOnConsecutiveCalls('a', 'b', 'c');
330
331
        $this->assertEquals('a', $mock->doSomething());
332
        $this->assertEquals('b', $mock->doSomething());
333
        $this->assertEquals('c', $mock->doSomething());
334
    }
335
336
    public function testStaticMethodCallback(): void
337
    {
338
        $mock = $this->getMockBuilder(SomeClass::class)
339
                     ->setMethods(['doSomething'])
340
                     ->getMock();
341
342
        $mock->expects($this->once())
343
             ->method('doSomething')
344
             ->will($this->returnCallback(['MethodCallback', 'staticCallback']));
345
346
        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
347
    }
348
349
    public function testPublicMethodCallback(): void
350
    {
351
        $mock = $this->getMockBuilder(SomeClass::class)
352
                     ->setMethods(['doSomething'])
353
                     ->getMock();
354
355
        $mock->expects($this->once())
356
             ->method('doSomething')
357
             ->will($this->returnCallback([new MethodCallback, 'nonStaticCallback']));
358
359
        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
360
    }
361
362
    public function testMockClassOnlyGeneratedOnce(): void
363
    {
364
        $mock1 = $this->getMockBuilder(AnInterface::class)
365
                     ->getMock();
366
367
        $mock2 = $this->getMockBuilder(AnInterface::class)
368
                     ->getMock();
369
370
        $this->assertEquals(\get_class($mock1), \get_class($mock2));
371
    }
372
373
    public function testMockClassDifferentForPartialMocks(): void
374
    {
375
        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
376
                      ->getMock();
377
378
        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
379
                      ->setMethods(['doSomething'])
380
                      ->getMock();
381
382
        $mock3 = $this->getMockBuilder(PartialMockTestClass::class)
383
                      ->setMethods(['doSomething'])
384
                      ->getMock();
385
386
        $mock4 = $this->getMockBuilder(PartialMockTestClass::class)
387
                      ->setMethods(['doAnotherThing'])
388
                      ->getMock();
389
390
        $mock5 = $this->getMockBuilder(PartialMockTestClass::class)
391
                      ->setMethods(['doAnotherThing'])
392
                      ->getMock();
393
394
        $this->assertNotEquals(\get_class($mock1), \get_class($mock2));
395
        $this->assertNotEquals(\get_class($mock1), \get_class($mock3));
396
        $this->assertNotEquals(\get_class($mock1), \get_class($mock4));
397
        $this->assertNotEquals(\get_class($mock1), \get_class($mock5));
398
        $this->assertEquals(\get_class($mock2), \get_class($mock3));
399
        $this->assertNotEquals(\get_class($mock2), \get_class($mock4));
400
        $this->assertNotEquals(\get_class($mock2), \get_class($mock5));
401
        $this->assertEquals(\get_class($mock4), \get_class($mock5));
402
    }
403
404
    public function testMockClassStoreOverrulable(): void
405
    {
406
        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
407
                      ->getMock();
408
409
        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
410
                      ->setMockClassName('MyMockClassNameForPartialMockTestClass1')
411
                      ->getMock();
412
413
        $mock3 = $this->getMockBuilder(PartialMockTestClass::class)
414
                      ->getMock();
415
416
        $mock4 = $this->getMockBuilder(PartialMockTestClass::class)
417
                      ->setMethods(['doSomething'])
418
                      ->setMockClassName('AnotherMockClassNameForPartialMockTestClass')
419
                      ->getMock();
420
421
        $mock5 = $this->getMockBuilder(PartialMockTestClass::class)
422
                      ->setMockClassName('MyMockClassNameForPartialMockTestClass2')
423
                      ->getMock();
424
425
        $this->assertNotEquals(\get_class($mock1), \get_class($mock2));
426
        $this->assertEquals(\get_class($mock1), \get_class($mock3));
427
        $this->assertNotEquals(\get_class($mock1), \get_class($mock4));
428
        $this->assertNotEquals(\get_class($mock2), \get_class($mock3));
429
        $this->assertNotEquals(\get_class($mock2), \get_class($mock4));
430
        $this->assertNotEquals(\get_class($mock2), \get_class($mock5));
431
        $this->assertNotEquals(\get_class($mock3), \get_class($mock4));
432
        $this->assertNotEquals(\get_class($mock3), \get_class($mock5));
433
        $this->assertNotEquals(\get_class($mock4), \get_class($mock5));
434
    }
435
436
    public function testGetMockWithFixedClassNameCanProduceTheSameMockTwice(): void
437
    {
438
        $mock = $this->getMockBuilder(stdClass::class)->setMockClassName('FixedName')->getMock();
439
        $this->assertInstanceOf(stdClass::class, $mock);
440
    }
441
442
    public function testOriginalConstructorSettingConsidered(): void
443
    {
444
        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
445
                      ->getMock();
446
447
        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
448
                      ->disableOriginalConstructor()
449
                      ->getMock();
450
451
        $this->assertTrue($mock1->constructorCalled);
0 ignored issues
show
Bug introduced by
Accessing constructorCalled on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
452
        $this->assertFalse($mock2->constructorCalled);
453
    }
454
455
    public function testOriginalCloneSettingConsidered(): void
456
    {
457
        $mock1 = $this->getMockBuilder(PartialMockTestClass::class)
458
                      ->getMock();
459
460
        $mock2 = $this->getMockBuilder(PartialMockTestClass::class)
461
                      ->disableOriginalClone()
462
                      ->getMock();
463
464
        $this->assertNotEquals(\get_class($mock1), \get_class($mock2));
465
    }
466
467
    public function testGetMockForAbstractClass(): void
468
    {
469
        $mock = $this->getMockBuilder(AbstractMockTestClass::class)
470
                     ->getMock();
471
472
        $mock->expects($this->never())
473
             ->method('doSomething');
474
    }
475
476
    /**
477
     * @dataProvider traversableProvider
478
     */
479
    public function testGetMockForTraversable($type): void
480
    {
481
        $mock = $this->getMockBuilder($type)
482
                     ->getMock();
483
484
        $this->assertInstanceOf(Traversable::class, $mock);
485
    }
486
487
    public function testMultipleInterfacesCanBeMockedInSingleObject(): void
488
    {
489
        $mock = $this->getMockBuilder([AnInterface::class, AnotherInterface::class])
490
                     ->getMock();
491
492
        $this->assertInstanceOf(AnInterface::class, $mock);
493
        $this->assertInstanceOf(AnotherInterface::class, $mock);
494
    }
495
496
    public function testGetMockForTrait(): void
497
    {
498
        $mock = $this->getMockForTrait(AbstractTrait::class);
499
500
        $mock->expects($this->never())
501
             ->method('doSomething');
502
503
        $parent = \get_parent_class($mock);
504
        $traits = \class_uses($parent, false);
505
506
        $this->assertContains(AbstractTrait::class, $traits);
507
    }
508
509
    public function testClonedMockObjectShouldStillEqualTheOriginal(): void
510
    {
511
        $a = $this->getMockBuilder(stdClass::class)
512
                  ->getMock();
513
514
        $b = clone $a;
515
516
        $this->assertEquals($a, $b);
517
    }
518
519
    public function testMockObjectsConstructedIndepentantlyShouldBeEqual(): void
520
    {
521
        $a = $this->getMockBuilder(stdClass::class)
522
                  ->getMock();
523
524
        $b = $this->getMockBuilder(stdClass::class)
525
                  ->getMock();
526
527
        $this->assertEquals($a, $b);
528
    }
529
530
    public function testMockObjectsConstructedIndepentantlyShouldNotBeTheSame(): void
531
    {
532
        $a = $this->getMockBuilder(stdClass::class)
533
                  ->getMock();
534
535
        $b = $this->getMockBuilder(stdClass::class)
536
                  ->getMock();
537
538
        $this->assertNotSame($a, $b);
539
    }
540
541
    public function testClonedMockObjectCanBeUsedInPlaceOfOriginalOne(): void
542
    {
543
        $x = $this->getMockBuilder(stdClass::class)
544
                  ->getMock();
545
546
        $y = clone $x;
547
548
        $mock = $this->getMockBuilder(stdClass::class)
549
                     ->setMethods(['foo'])
550
                     ->getMock();
551
552
        $mock->expects($this->once())
553
             ->method('foo')
554
             ->with($this->equalTo($x));
555
556
        $mock->foo($y);
557
    }
558
559
    public function testClonedMockObjectIsNotIdenticalToOriginalOne(): void
560
    {
561
        $x = $this->getMockBuilder(stdClass::class)
562
                  ->getMock();
563
564
        $y = clone $x;
565
566
        $mock = $this->getMockBuilder(stdClass::class)
567
                     ->setMethods(['foo'])
568
                     ->getMock();
569
570
        $mock->expects($this->once())
571
             ->method('foo')
572
             ->with($this->logicalNot($this->identicalTo($x)));
573
574
        $mock->foo($y);
575
    }
576
577
    public function testObjectMethodCallWithArgumentCloningEnabled(): void
578
    {
579
        $expectedObject = new stdClass;
580
581
        $mock = $this->getMockBuilder('SomeClass')
582
                     ->setMethods(['doSomethingElse'])
583
                     ->enableArgumentCloning()
584
                     ->getMock();
585
586
        $actualArguments = [];
587
588
        $mock->expects($this->any())
589
             ->method('doSomethingElse')
590
             ->will(
591
                 $this->returnCallback(
592
                     function () use (&$actualArguments): void {
593
                         $actualArguments = \func_get_args();
594
                     }
595
                 )
596
             );
597
598
        $mock->doSomethingElse($expectedObject);
599
600
        $this->assertCount(1, $actualArguments);
601
        $this->assertEquals($expectedObject, $actualArguments[0]);
602
        $this->assertNotSame($expectedObject, $actualArguments[0]);
603
    }
604
605
    public function testObjectMethodCallWithArgumentCloningDisabled(): void
606
    {
607
        $expectedObject = new stdClass;
608
609
        $mock = $this->getMockBuilder('SomeClass')
610
                     ->setMethods(['doSomethingElse'])
611
                     ->disableArgumentCloning()
612
                     ->getMock();
613
614
        $actualArguments = [];
615
616
        $mock->expects($this->any())
617
             ->method('doSomethingElse')
618
             ->will(
619
                 $this->returnCallback(
620
                     function () use (&$actualArguments): void {
621
                         $actualArguments = \func_get_args();
622
                     }
623
                 )
624
             );
625
626
        $mock->doSomethingElse($expectedObject);
627
628
        $this->assertCount(1, $actualArguments);
629
        $this->assertSame($expectedObject, $actualArguments[0]);
630
    }
631
632
    public function testArgumentCloningOptionGeneratesUniqueMock(): void
633
    {
634
        $mockWithCloning = $this->getMockBuilder('SomeClass')
635
                                ->setMethods(['doSomethingElse'])
636
                                ->enableArgumentCloning()
637
                                ->getMock();
638
639
        $mockWithoutCloning = $this->getMockBuilder('SomeClass')
640
                                   ->setMethods(['doSomethingElse'])
641
                                   ->disableArgumentCloning()
642
                                   ->getMock();
643
644
        $this->assertNotEquals($mockWithCloning, $mockWithoutCloning);
645
    }
646
647
    public function testVerificationOfMethodNameFailsWithoutParameters(): void
648
    {
649
        $mock = $this->getMockBuilder(SomeClass::class)
650
                     ->setMethods(['right', 'wrong'])
651
                     ->getMock();
652
653
        $mock->expects($this->once())
654
             ->method('right');
655
656
        $mock->wrong();
657
658
        try {
659
            $mock->__phpunit_verify();
660
            $this->fail('Expected exception');
661
        } catch (ExpectationFailedException $e) {
662
            $this->assertSame(
663
                "Expectation failed for method name is equal to 'right' when invoked 1 time(s).\n" .
664
                'Method was expected to be called 1 times, actually called 0 times.' . "\n",
665
                $e->getMessage()
666
            );
667
        }
668
669
        $this->resetMockObjects();
670
    }
671
672
    public function testVerificationOfMethodNameFailsWithParameters(): void
673
    {
674
        $mock = $this->getMockBuilder(SomeClass::class)
675
                     ->setMethods(['right', 'wrong'])
676
                     ->getMock();
677
678
        $mock->expects($this->once())
679
             ->method('right');
680
681
        $mock->wrong();
682
683
        try {
684
            $mock->__phpunit_verify();
685
            $this->fail('Expected exception');
686
        } catch (ExpectationFailedException $e) {
687
            $this->assertSame(
688
                "Expectation failed for method name is equal to 'right' when invoked 1 time(s).\n" .
689
                'Method was expected to be called 1 times, actually called 0 times.' . "\n",
690
                $e->getMessage()
691
            );
692
        }
693
694
        $this->resetMockObjects();
695
    }
696
697
    public function testVerificationOfMethodNameFailsWithWrongParameters(): void
698
    {
699
        $mock = $this->getMockBuilder(SomeClass::class)
700
                     ->setMethods(['right', 'wrong'])
701
                     ->getMock();
702
703
        $mock->expects($this->once())
704
             ->method('right')
705
             ->with(['first', 'second']);
706
707
        try {
708
            $mock->right(['second']);
709
        } catch (ExpectationFailedException $e) {
710
            $this->assertSame(
711
                "Expectation failed for method name is equal to 'right' when invoked 1 time(s)\n" .
712
                'Parameter 0 for invocation SomeClass::right(Array (...)) does not match expected value.' . "\n" .
713
                'Failed asserting that two arrays are equal.',
714
                $e->getMessage()
715
            );
716
        }
717
718
        try {
719
            $mock->__phpunit_verify();
720
721
            // CHECKOUT THIS MORE CAREFULLY
722
//            $this->fail('Expected exception');
723
        } catch (ExpectationFailedException $e) {
724
            $this->assertSame(
725
                "Expectation failed for method name is equal to 'right' when invoked 1 time(s).\n" .
726
                'Parameter 0 for invocation SomeClass::right(Array (...)) does not match expected value.' . "\n" .
727
                'Failed asserting that two arrays are equal.' . "\n" .
728
                '--- Expected' . "\n" .
729
                '+++ Actual' . "\n" .
730
                '@@ @@' . "\n" .
731
                ' Array (' . "\n" .
732
                '-    0 => \'first\'' . "\n" .
733
                '-    1 => \'second\'' . "\n" .
734
                '+    0 => \'second\'' . "\n" .
735
                ' )' . "\n",
736
                $e->getMessage()
737
            );
738
        }
739
740
        $this->resetMockObjects();
741
    }
742
743
    public function testVerificationOfNeverFailsWithEmptyParameters(): void
744
    {
745
        $mock = $this->getMockBuilder(SomeClass::class)
746
                     ->setMethods(['right', 'wrong'])
747
                     ->getMock();
748
749
        $mock->expects($this->never())
750
             ->method('right')
751
             ->with();
752
753
        try {
754
            $mock->right();
755
            $this->fail('Expected exception');
756
        } catch (ExpectationFailedException $e) {
757
            $this->assertSame(
758
                'SomeClass::right() was not expected to be called.',
759
                $e->getMessage()
760
            );
761
        }
762
763
        $this->resetMockObjects();
764
    }
765
766
    public function testVerificationOfNeverFailsWithAnyParameters(): void
767
    {
768
        $mock = $this->getMockBuilder(SomeClass::class)
769
                     ->setMethods(['right', 'wrong'])
770
                     ->getMock();
771
772
        $mock->expects($this->never())
773
             ->method('right')
774
             ->withAnyParameters();
775
776
        try {
777
            $mock->right();
778
            $this->fail('Expected exception');
779
        } catch (ExpectationFailedException $e) {
780
            $this->assertSame(
781
                'SomeClass::right() was not expected to be called.',
782
                $e->getMessage()
783
            );
784
        }
785
786
        $this->resetMockObjects();
787
    }
788
789
    public function testWithAnythingInsteadOfWithAnyParameters(): void
790
    {
791
        $mock = $this->getMockBuilder(SomeClass::class)
792
                     ->setMethods(['right', 'wrong'])
793
                     ->getMock();
794
795
        $mock->expects($this->once())
796
             ->method('right')
797
             ->with($this->anything());
798
799
        try {
800
            $mock->right();
801
            $this->fail('Expected exception');
802
        } catch (ExpectationFailedException $e) {
803
            $this->assertSame(
804
                "Expectation failed for method name is equal to 'right' when invoked 1 time(s)\n" .
805
                'Parameter count for invocation SomeClass::right() is too low.' . "\n" .
806
                'To allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead.',
807
                $e->getMessage()
808
            );
809
        }
810
811
        $this->resetMockObjects();
812
    }
813
814
    /**
815
     * See https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81
816
     */
817
    public function testMockArgumentsPassedByReference(): void
818
    {
819
        $foo = $this->getMockBuilder('MethodCallbackByReference')
820
                    ->setMethods(['bar'])
821
                    ->disableOriginalConstructor()
822
                    ->disableArgumentCloning()
823
                    ->getMock();
824
825
        $foo->expects($this->any())
826
            ->method('bar')
827
            ->will($this->returnCallback([$foo, 'callback']));
828
829
        $a = $b = $c = 0;
830
831
        $foo->bar($a, $b, $c);
832
833
        $this->assertEquals(1, $b);
834
    }
835
836
    /**
837
     * See https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81
838
     */
839
    public function testMockArgumentsPassedByReference2(): void
840
    {
841
        $foo = $this->getMockBuilder('MethodCallbackByReference')
842
                    ->disableOriginalConstructor()
843
                    ->disableArgumentCloning()
844
                    ->getMock();
845
846
        $foo->expects($this->any())
847
            ->method('bar')
848
            ->will($this->returnCallback(
849
                function (&$a, &$b, $c): void {
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

849
                function (&$a, &$b, /** @scrutinizer ignore-unused */ $c): void {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
850
                    $b = 1;
851
                }
852
            ));
853
854
        $a = $b = $c = 0;
855
856
        $foo->bar($a, $b, $c);
857
858
        $this->assertEquals(1, $b);
859
    }
860
861
    /**
862
     * @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/116
863
     */
864
    public function testMockArgumentsPassedByReference3(): void
865
    {
866
        $foo = $this->getMockBuilder('MethodCallbackByReference')
867
                    ->setMethods(['bar'])
868
                    ->disableOriginalConstructor()
869
                    ->disableArgumentCloning()
870
                    ->getMock();
871
872
        $a = new stdClass;
873
        $b = $c = 0;
874
875
        $foo->expects($this->any())
876
            ->method('bar')
877
            ->with($a, $b, $c)
878
            ->will($this->returnCallback([$foo, 'callback']));
879
880
        $this->assertNull($foo->bar($a, $b, $c));
881
    }
882
883
    /**
884
     * @see https://github.com/sebastianbergmann/phpunit/issues/796
885
     */
886
    public function testMockArgumentsPassedByReference4(): void
887
    {
888
        $foo = $this->getMockBuilder('MethodCallbackByReference')
889
                    ->setMethods(['bar'])
890
                    ->disableOriginalConstructor()
891
                    ->disableArgumentCloning()
892
                    ->getMock();
893
894
        $a = new stdClass;
895
        $b = $c = 0;
896
897
        $foo->expects($this->any())
898
            ->method('bar')
899
            ->with($this->isInstanceOf(stdClass::class), $b, $c)
900
            ->will($this->returnCallback([$foo, 'callback']));
901
902
        $this->assertNull($foo->bar($a, $b, $c));
903
    }
904
905
    /**
906
     * @requires extension soap
907
     */
908
    public function testCreateMockFromWsdl(): void
909
    {
910
        $mock = $this->getMockFromWsdl(TEST_FILES_PATH . 'GoogleSearch.wsdl', 'WsdlMock');
911
912
        $this->assertStringStartsWith(
913
            'Mock_WsdlMock_',
914
            \get_class($mock)
915
        );
916
    }
917
918
    /**
919
     * @requires extension soap
920
     */
921
    public function testCreateNamespacedMockFromWsdl(): void
922
    {
923
        $mock = $this->getMockFromWsdl(TEST_FILES_PATH . 'GoogleSearch.wsdl', 'My\\Space\\WsdlMock');
924
925
        $this->assertStringStartsWith(
926
            'Mock_WsdlMock_',
927
            \get_class($mock)
928
        );
929
    }
930
931
    /**
932
     * @requires extension soap
933
     */
934
    public function testCreateTwoMocksOfOneWsdlFile(): void
935
    {
936
        $a = $this->getMockFromWsdl(TEST_FILES_PATH . 'GoogleSearch.wsdl');
937
        $b = $this->getMockFromWsdl(TEST_FILES_PATH . 'GoogleSearch.wsdl');
938
939
        $this->assertStringStartsWith('Mock_GoogleSearch_', \get_class($a));
940
        $this->assertEquals(\get_class($a), \get_class($b));
941
    }
942
943
    /**
944
     * @see      https://github.com/sebastianbergmann/phpunit/issues/2573
945
     * @ticket   2573
946
     * @requires extension soap
947
     */
948
    public function testCreateMockOfWsdlFileWithSpecialChars(): void
949
    {
950
        $mock = $this->getMockFromWsdl(TEST_FILES_PATH . 'Go ogle-Sea.rch.wsdl');
951
952
        $this->assertStringStartsWith('Mock_GoogleSearch_', \get_class($mock));
953
    }
954
955
    /**
956
     * @see    https://github.com/sebastianbergmann/phpunit-mock-objects/issues/156
957
     * @ticket 156
958
     */
959
    public function testInterfaceWithStaticMethodCanBeStubbed(): void
960
    {
961
        $this->assertInstanceOf(
962
            InterfaceWithStaticMethod::class,
963
            $this->getMockBuilder(InterfaceWithStaticMethod::class)->getMock()
964
        );
965
    }
966
967
    public function testInvokingStubbedStaticMethodRaisesException(): void
968
    {
969
        $mock = $this->getMockBuilder(ClassWithStaticMethod::class)->getMock();
970
971
        $this->expectException(\PHPUnit\Framework\MockObject\BadMethodCallException::class);
972
973
        $mock->staticMethod();
974
    }
975
976
    /**
977
     * @see    https://github.com/sebastianbergmann/phpunit-mock-objects/issues/171
978
     * @ticket 171
979
     */
980
    public function testStubForClassThatImplementsSerializableCanBeCreatedWithoutInvokingTheConstructor(): void
981
    {
982
        $this->assertInstanceOf(
983
            ClassThatImplementsSerializable::class,
984
            $this->getMockBuilder(ClassThatImplementsSerializable::class)
985
                 ->disableOriginalConstructor()
986
                 ->getMock()
987
        );
988
    }
989
990
    public function testGetMockForClassWithSelfTypeHint(): void
991
    {
992
        $this->assertInstanceOf(
993
            ClassWithSelfTypeHint::class,
994
            $this->getMockBuilder(ClassWithSelfTypeHint::class)->getMock()
995
        );
996
    }
997
998
    public function testStringableClassDoesNotThrow(): void
999
    {
1000
        /** @var PHPUnit\Framework\MockObject\MockObject|StringableClass $mock */
1001
        $mock = $this->getMockBuilder(StringableClass::class)->getMock();
1002
1003
        $this->assertIsString((string) $mock);
1004
    }
1005
1006
    public function testStringableClassCanBeMocked(): void
1007
    {
1008
        /** @var PHPUnit\Framework\MockObject\MockObject|StringableClass $mock */
1009
        $mock = $this->getMockBuilder(StringableClass::class)->getMock();
1010
1011
        $mock->method('__toString')->willReturn('foo');
1012
1013
        $this->assertSame('foo', (string) $mock);
1014
    }
1015
1016
    public function traversableProvider(): array
1017
    {
1018
        return [
1019
            ['Traversable'],
1020
            ['\Traversable'],
1021
            ['TraversableMockTestInterface'],
1022
            [['Traversable']],
1023
            [['Iterator', 'Traversable']],
1024
            [['\Iterator', '\Traversable']],
1025
        ];
1026
    }
1027
1028
    public function testParameterCallbackConstraintOnlyEvaluatedOnce(): void
1029
    {
1030
        $mock                  = $this->getMockBuilder(Foo::class)->setMethods(['bar'])->getMock();
1031
        $expectedNumberOfCalls = 1;
1032
        $callCount             = 0;
1033
1034
        $mock->expects($this->exactly($expectedNumberOfCalls))->method('bar')
1035
            ->with($this->callback(function ($argument) use (&$callCount) {
1036
                return $argument === 'call_' . $callCount++;
1037
            }));
1038
1039
        for ($i = 0; $i < $expectedNumberOfCalls; $i++) {
1040
            $mock->bar('call_' . $i);
1041
        }
1042
    }
1043
1044
    public function testReturnTypesAreMockedCorrectly(): void
1045
    {
1046
        /** @var ClassWithAllPossibleReturnTypes|MockObject $stub */
1047
        $stub = $this->createMock(ClassWithAllPossibleReturnTypes::class);
1048
1049
        $this->assertNull($stub->methodWithNoReturnTypeDeclaration());
1050
        $this->assertSame('', $stub->methodWithStringReturnTypeDeclaration());
1051
        $this->assertSame(0.0, $stub->methodWithFloatReturnTypeDeclaration());
1052
        $this->assertSame(0, $stub->methodWithIntReturnTypeDeclaration());
1053
        $this->assertFalse($stub->methodWithBoolReturnTypeDeclaration());
1054
        $this->assertSame([], $stub->methodWithArrayReturnTypeDeclaration());
1055
        $this->assertInstanceOf(MockObject::class, $stub->methodWithClassReturnTypeDeclaration());
1056
    }
1057
1058
    public function testDisableAutomaticReturnValueGeneration(): void
1059
    {
1060
        $mock = $this->getMockBuilder(SomeClass::class)
1061
            ->disableAutoReturnValueGeneration()
1062
            ->getMock();
1063
1064
        $this->expectException(ExpectationFailedException::class);
1065
        $this->expectExceptionMessage(
1066
            'Return value inference disabled and no expectation set up for SomeClass::doSomethingElse()'
1067
        );
1068
1069
        $mock->doSomethingElse(1);
1070
    }
1071
1072
    public function testDisableAutomaticReturnValueGenerationWithToString(): void
1073
    {
1074
        /** @var PHPUnit\Framework\MockObject\MockObject|StringableClass $mock */
1075
        $mock = $this->getMockBuilder(StringableClass::class)
1076
            ->disableAutoReturnValueGeneration()
1077
            ->getMock();
1078
1079
        (string) $mock;
1080
1081
        try {
1082
            $mock->__phpunit_verify();
1083
            $this->fail('Exception expected');
1084
        } catch (ExpectationFailedException $e) {
1085
            $this->assertSame(
1086
                'Return value inference disabled and no expectation set up for StringableClass::__toString()',
1087
                $e->getMessage()
1088
            );
1089
        }
1090
1091
        $this->resetMockObjects();
1092
    }
1093
1094
    public function testVoidReturnTypeIsMockedCorrectly(): void
1095
    {
1096
        /** @var ClassWithAllPossibleReturnTypes|MockObject $stub */
1097
        $stub = $this->createMock(ClassWithAllPossibleReturnTypes::class);
1098
1099
        $this->assertNull($stub->methodWithVoidReturnTypeDeclaration());
1100
    }
1101
1102
    /**
1103
     * @requires PHP 7.2
1104
     */
1105
    public function testObjectReturnTypeIsMockedCorrectly(): void
1106
    {
1107
        /** @var ClassWithAllPossibleReturnTypes|MockObject $stub */
1108
        $stub = $this->createMock(ClassWithAllPossibleReturnTypes::class);
1109
1110
        $this->assertInstanceOf(stdClass::class, $stub->methodWithObjectReturnTypeDeclaration());
1111
    }
1112
1113
    public function testTraitCanBeDoubled(): void
1114
    {
1115
        $object = $this->getObjectForTrait(ExampleTrait::class);
1116
1117
        $this->assertSame('ohHai', $object->ohHai());
1118
    }
1119
1120
    public function testTraitWithConstructorCanBeDoubled(): void
1121
    {
1122
        $object = $this->getObjectForTrait(TraitWithConstructor::class, ['value']);
1123
1124
        $this->assertSame('value', $object->value());
1125
    }
1126
1127
    private function resetMockObjects(): void
1128
    {
1129
        $refl = new ReflectionObject($this);
1130
        $refl = $refl->getParentClass();
1131
        $prop = $refl->getProperty('mockObjects');
1132
        $prop->setAccessible(true);
1133
        $prop->setValue($this, []);
1134
    }
1135
}
1136