Completed
Pull Request — master (#668)
by Dave
04:20 queued 02:13
created

Mock::allows()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * Mockery
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://github.com/padraic/mockery/blob/master/LICENSE
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to [email protected] so we can send you a copy immediately.
14
 *
15
 * @category   Mockery
16
 * @package    Mockery
17
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
18
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
19
 */
20
21
namespace Mockery;
22
23
use Mockery\HigherOrderMessage;
24
use Mockery\MockInterface;
25
use Mockery\ExpectsHigherOrderMessage;
26
27
class Mock implements MockInterface
28
{
29
    /**
30
     * Stores an array of all expectation directors for this mock
31
     *
32
     * @var array
33
     */
34
    protected $_mockery_expectations = array();
35
36
    /**
37
     * Stores an inital number of expectations that can be manipulated
38
     * while using the getter method.
39
     *
40
     * @var int
41
     */
42
    protected $_mockery_expectations_count = 0;
43
44
    /**
45
     * Flag to indicate whether we can ignore method calls missing from our
46
     * expectations
47
     *
48
     * @var bool
49
     */
50
    protected $_mockery_ignoreMissing = false;
51
52
    /**
53
     * Flag to indicate whether we can defer method calls missing from our
54
     * expectations
55
     *
56
     * @var bool
57
     */
58
    protected $_mockery_deferMissing = false;
59
60
    /**
61
     * Flag to indicate whether this mock was verified
62
     *
63
     * @var bool
64
     */
65
    protected $_mockery_verified = false;
66
67
    /**
68
     * Given name of the mock
69
     *
70
     * @var string
71
     */
72
    protected $_mockery_name = null;
73
74
    /**
75
     * Order number of allocation
76
     *
77
     * @var int
78
     */
79
    protected $_mockery_allocatedOrder = 0;
80
81
    /**
82
     * Current ordered number
83
     *
84
     * @var int
85
     */
86
    protected $_mockery_currentOrder = 0;
87
88
    /**
89
     * Ordered groups
90
     *
91
     * @var array
92
     */
93
    protected $_mockery_groups = array();
94
95
    /**
96
     * Mock container containing this mock object
97
     *
98
     * @var \Mockery\Container
99
     */
100
    protected $_mockery_container = null;
101
102
    /**
103
     * Instance of a core object on which methods are called in the event
104
     * it has been set, and an expectation for one of the object's methods
105
     * does not exist. This implements a simple partial mock proxy system.
106
     *
107
     * @var object
108
     */
109
    protected $_mockery_partial = null;
110
111
    /**
112
     * Flag to indicate we should ignore all expectations temporarily. Used
113
     * mainly to prevent expectation matching when in the middle of a mock
114
     * object recording session.
115
     *
116
     * @var bool
117
     */
118
    protected $_mockery_disableExpectationMatching = false;
119
120
    /**
121
     * Stores all stubbed public methods separate from any on-object public
122
     * properties that may exist.
123
     *
124
     * @var array
125
     */
126
    protected $_mockery_mockableProperties = array();
127
128
    /**
129
     * @var array
130
     */
131
    protected $_mockery_mockableMethods = array();
132
133
    /**
134
     * Just a local cache for this mock's target's methods
135
     *
136
     * @var ReflectionMethod[]
137
     */
138
    protected static $_mockery_methods;
139
140
    protected $_mockery_allowMockingProtectedMethods = false;
141
142
    protected $_mockery_receivedMethodCalls;
143
144
    /**
145
     * If shouldIgnoreMissing is called, this value will be returned on all calls to missing methods
146
     * @var mixed
147
     */
148
    protected $_mockery_defaultReturnValue = null;
149
150
    /**
151
     * We want to avoid constructors since class is copied to Generator.php
152
     * for inclusion on extending class definitions.
153
     *
154
     * @param \Mockery\Container $container
155
     * @param object $partialObject
156
     * @return void
157
     */
158
    public function mockery_init(\Mockery\Container $container = null, $partialObject = null)
159
    {
160
        if (is_null($container)) {
161
            $container = new \Mockery\Container;
162
        }
163
        $this->_mockery_container = $container;
164
        if (!is_null($partialObject)) {
165
            $this->_mockery_partial = $partialObject;
166
        }
167
168
        if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
169
            foreach ($this->mockery_getMethods() as $method) {
170
                if ($method->isPublic() && !$method->isStatic()) {
171
                    $this->_mockery_mockableMethods[] = $method->getName();
172
                }
173
            }
174
        }
175
    }
176
177
    /**
178
     * Set expected method calls
179
     *
180
     * @param null|string $methodName,... one or many methods that are expected to be called in this mock
181
     * @return \Mockery\ExpectationInterface|\Mockery\HigherOrderMessage
182
     */
183
    public function shouldReceive($methodName = null)
184
    {
185
        if ($methodName === null) {
186
            return new HigherOrderMessage($this, "shouldReceive");
187
        }
188
189
        foreach (func_get_args() as $method) {
190
            if ("" == $method) {
191
                throw new \InvalidArgumentException("Received empty method name");
192
            }
193
        }
194
195
        /** @var array $nonPublicMethods */
196
        $nonPublicMethods = $this->getNonPublicMethods();
197
198
        $self = $this;
199
        $allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;
200
201
        $lastExpectation = \Mockery::parseShouldReturnArgs(
202
            $this, func_get_args(), function ($method) use ($self, $nonPublicMethods, $allowMockingProtectedMethods) {
203
                $rm = $self->mockery_getMethod($method);
204
                if ($rm) {
205
                    if ($rm->isPrivate()) {
206
                        throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method");
207
                    }
208
                    if (!$allowMockingProtectedMethods && $rm->isProtected()) {
209
                        throw new \InvalidArgumentException("$method() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object.");
210
                    }
211
                }
212
213
                $director = $self->mockery_getExpectationsFor($method);
214
                if (!$director) {
215
                    $director = new \Mockery\ExpectationDirector($method, $self);
216
                    $self->mockery_setExpectationsFor($method, $director);
217
                }
218
                $expectation = new \Mockery\Expectation($self, $method);
219
                $director->addExpectation($expectation);
220
                return $expectation;
221
            }
222
        );
223
        return $lastExpectation;
224
    }
225
226
    // start method allows
227
    /**
228
     * @return HigherOrderMessage
229
     */
230
    public function allows()
231
    {
232
        return $this->shouldReceive();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->shouldReceive(); of type Mockery\HigherOrderMessa...ry\CompositeExpectation adds the type Mockery\CompositeExpectation to the return on line 232 which is incompatible with the return type documented by Mockery\Mock::allows of type Mockery\HigherOrderMessage.
Loading history...
233
    }
234
    // end method allows
235
236
    // start method expects
237
    /**
238
     * @return ExpectsHigherOrderMessage
239
     */
240
    public function expects()
241
    {
242
        return new ExpectsHigherOrderMessage($this);
243
    }
244
    // end method expects
245
     
246
     
247
    /**
248
     * Shortcut method for setting an expectation that a method should not be called.
249
     *
250
     * @param null|string $methodName,... one or many methods that are expected not to be called in this mock
251
     * @return \Mockery\Expectation|\Mockery\HigherOrderMessage
252
     */
253
    public function shouldNotReceive($methodName = null)
254
    {
255
        if ($methodName === null) {
256
            return new HigherOrderMessage($this, "shouldNotReceive");
257
        }
258
259
        $expectation = call_user_func_array(array($this, 'shouldReceive'), func_get_args());
260
        $expectation->never();
261
        return $expectation;
262
    }
263
264
    /**
265
     * Allows additional methods to be mocked that do not explicitly exist on mocked class
266
     * @param String $method name of the method to be mocked
267
     * @return Mock
268
     */
269
    public function shouldAllowMockingMethod($method)
270
    {
271
        $this->_mockery_mockableMethods[] = $method;
272
        return $this;
273
    }
274
275
    /**
276
     * Set mock to ignore unexpected methods and return Undefined class
277
     * @param mixed $returnValue the default return value for calls to missing functions on this mock
278
     * @return Mock
279
     */
280
    public function shouldIgnoreMissing($returnValue = null)
281
    {
282
        $this->_mockery_ignoreMissing = true;
283
        $this->_mockery_defaultReturnValue = $returnValue;
284
        return $this;
285
    }
286
287
    public function asUndefined()
288
    {
289
        $this->_mockery_ignoreMissing = true;
290
        $this->_mockery_defaultReturnValue = new \Mockery\Undefined;
291
        return $this;
292
    }
293
294
    /**
295
     * @return Mock
296
     */
297
    public function shouldAllowMockingProtectedMethods()
298
    {
299
        $this->_mockery_allowMockingProtectedMethods = true;
300
        return $this;
301
    }
302
303
304
    /**
305
     * Set mock to defer unexpected methods to it's parent
306
     *
307
     * This is particularly useless for this class, as it doesn't have a parent,
308
     * but included for completeness
309
     *
310
     * @return Mock
311
     */
312
    public function shouldDeferMissing()
313
    {
314
        $this->_mockery_deferMissing = true;
315
        return $this;
316
    }
317
318
    /**
319
     * Create an obviously worded alias to shouldDeferMissing()
320
     *
321
     * @return Mock
322
     */
323
    public function makePartial()
324
    {
325
        return $this->shouldDeferMissing();
326
    }
327
328
    /**
329
     * Accepts a closure which is executed with an object recorder which proxies
330
     * to the partial source object. The intent being to record the
331
     * interactions of a concrete object as a set of expectations on the
332
     * current mock object. The partial may then be passed to a second process
333
     * to see if it fulfils the same (or exact same) contract as the original.
334
     *
335
     * @param Closure $closure
336
     */
337
    public function shouldExpect(\Closure $closure)
338
    {
339
        $recorder = new \Mockery\Recorder($this, $this->_mockery_partial);
340
        $this->_mockery_disableExpectationMatching = true;
341
        $closure($recorder);
342
        $this->_mockery_disableExpectationMatching = false;
343
        return $this;
344
    }
345
346
    /**
347
     * In the event shouldReceive() accepting one or more methods/returns,
348
     * this method will switch them from normal expectations to default
349
     * expectations
350
     *
351
     * @return self
352
     */
353
    public function byDefault()
354
    {
355
        foreach ($this->_mockery_expectations as $director) {
356
            $exps = $director->getExpectations();
357
            foreach ($exps as $exp) {
358
                $exp->byDefault();
359
            }
360
        }
361
        return $this;
362
    }
363
364
    /**
365
     * Capture calls to this mock
366
     */
367
    public function __call($method, array $args)
368
    {
369
        return $this->_mockery_handleMethodCall($method, $args);
370
    }
371
372
    public static function __callStatic($method, array $args)
373
    {
374
        return self::_mockery_handleStaticMethodCall($method, $args);
375
    }
376
377
    /**
378
     * Forward calls to this magic method to the __call method
379
     */
380
    public function __toString()
381
    {
382
        return $this->__call('__toString', array());
383
    }
384
385
    /**
386
     * Iterate across all expectation directors and validate each
387
     *
388
     * @throws \Mockery\CountValidator\Exception
389
     * @return void
390
     */
391
    public function mockery_verify()
392
    {
393
        if ($this->_mockery_verified) {
394
            return;
395
        }
396
        if (isset($this->_mockery_ignoreVerification)
397
            && $this->_mockery_ignoreVerification == true) {
398
            return;
399
        }
400
        $this->_mockery_verified = true;
401
        foreach ($this->_mockery_expectations as $director) {
402
            $director->verify();
403
        }
404
    }
405
406
    /**
407
     * Tear down tasks for this mock
408
     *
409
     * @return void
410
     */
411
    public function mockery_teardown()
412
    {
413
    }
414
415
    /**
416
     * Fetch the next available allocation order number
417
     *
418
     * @return int
419
     */
420
    public function mockery_allocateOrder()
421
    {
422
        $this->_mockery_allocatedOrder += 1;
423
        return $this->_mockery_allocatedOrder;
424
    }
425
426
    /**
427
     * Set ordering for a group
428
     *
429
     * @param mixed $group
430
     * @param int $order
431
     */
432
    public function mockery_setGroup($group, $order)
433
    {
434
        $this->_mockery_groups[$group] = $order;
435
    }
436
437
    /**
438
     * Fetch array of ordered groups
439
     *
440
     * @return array
441
     */
442
    public function mockery_getGroups()
443
    {
444
        return $this->_mockery_groups;
445
    }
446
447
    /**
448
     * Set current ordered number
449
     *
450
     * @param int $order
451
     */
452
    public function mockery_setCurrentOrder($order)
453
    {
454
        $this->_mockery_currentOrder = $order;
455
        return $this->_mockery_currentOrder;
456
    }
457
458
    /**
459
     * Get current ordered number
460
     *
461
     * @return int
462
     */
463
    public function mockery_getCurrentOrder()
464
    {
465
        return $this->_mockery_currentOrder;
466
    }
467
468
    /**
469
     * Validate the current mock's ordering
470
     *
471
     * @param string $method
472
     * @param int $order
473
     * @throws \Mockery\Exception
474
     * @return void
475
     */
476
    public function mockery_validateOrder($method, $order)
477
    {
478
        if ($order < $this->_mockery_currentOrder) {
479
            $exception = new \Mockery\Exception\InvalidOrderException(
480
                'Method ' . __CLASS__ . '::' . $method . '()'
481
                . ' called out of order: expected order '
482
                . $order . ', was ' . $this->_mockery_currentOrder
483
            );
484
            $exception->setMock($this)
485
                ->setMethodName($method)
486
                ->setExpectedOrder($order)
487
                ->setActualOrder($this->_mockery_currentOrder);
488
            throw $exception;
489
        }
490
        $this->mockery_setCurrentOrder($order);
491
    }
492
493
    /**
494
     * Gets the count of expectations for this mock
495
     *
496
     * @return int
497
     */
498
    public function mockery_getExpectationCount()
499
    {
500
        $count = $this->_mockery_expectations_count;
501
        foreach ($this->_mockery_expectations as $director) {
502
            $count += $director->getExpectationCount();
503
        }
504
        return $count;
505
    }
506
507
    /**
508
     * Return the expectations director for the given method
509
     *
510
     * @var string $method
511
     * @return \Mockery\ExpectationDirector|null
512
     */
513
    public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
514
    {
515
        $this->_mockery_expectations[$method] = $director;
516
    }
517
518
    /**
519
     * Return the expectations director for the given method
520
     *
521
     * @var string $method
522
     * @return \Mockery\ExpectationDirector|null
523
     */
524
    public function mockery_getExpectationsFor($method)
525
    {
526
        if (isset($this->_mockery_expectations[$method])) {
527
            return $this->_mockery_expectations[$method];
528
        }
529
    }
530
531
    /**
532
     * Find an expectation matching the given method and arguments
533
     *
534
     * @var string $method
535
     * @var array $args
536
     * @return \Mockery\Expectation|null
537
     */
538
    public function mockery_findExpectation($method, array $args)
539
    {
540
        if (!isset($this->_mockery_expectations[$method])) {
541
            return null;
542
        }
543
        $director = $this->_mockery_expectations[$method];
544
545
        return $director->findExpectation($args);
546
    }
547
548
    /**
549
     * Return the container for this mock
550
     *
551
     * @return \Mockery\Container
552
     */
553
    public function mockery_getContainer()
554
    {
555
        return $this->_mockery_container;
556
    }
557
558
    /**
559
     * Return the name for this mock
560
     *
561
     * @return string
562
     */
563
    public function mockery_getName()
564
    {
565
        return __CLASS__;
566
    }
567
568
    /**
569
     * @return array
570
     */
571
    public function mockery_getMockableProperties()
572
    {
573
        return $this->_mockery_mockableProperties;
574
    }
575
576
    public function __isset($name)
577
    {
578
        if (false === stripos($name, '_mockery_') && method_exists(get_parent_class($this), '__isset')) {
579
            return parent::__isset($name);
580
        }
581
582
        return false;
583
    }
584
585
    public function mockery_getExpectations()
586
    {
587
        return $this->_mockery_expectations;
588
    }
589
590
    /**
591
     * Calls a parent class method and returns the result. Used in a passthru
592
     * expectation where a real return value is required while still taking
593
     * advantage of expectation matching and call count verification.
594
     *
595
     * @param string $name
596
     * @param array $args
597
     * @return mixed
598
     */
599
    public function mockery_callSubjectMethod($name, array $args)
600
    {
601
        return call_user_func_array('parent::' . $name, $args);
602
    }
603
604
    /**
605
     * @return string[]
606
     */
607
    public function mockery_getMockableMethods()
608
    {
609
        return $this->_mockery_mockableMethods;
610
    }
611
612
    /**
613
     * @return bool
614
     */
615
    public function mockery_isAnonymous()
616
    {
617
        $rfc = new \ReflectionClass($this);
618
        $onlyImplementsMock = count($rfc->getInterfaces()) == 1;
619
        return (false === $rfc->getParentClass()) && $onlyImplementsMock;
620
    }
621
622
    public function __wakeup()
623
    {
624
        /**
625
         * This does not add __wakeup method support. It's a blind method and any
626
         * expected __wakeup work will NOT be performed. It merely cuts off
627
         * annoying errors where a __wakeup exists but is not essential when
628
         * mocking
629
         */
630
    }
631
632
    public function __destruct()
633
    {
634
        /**
635
         * Overrides real class destructor in case if class was created without original constructor
636
         */
637
    }
638
639
    public function mockery_getMethod($name)
640
    {
641
        foreach ($this->mockery_getMethods() as $method) {
642
            if ($method->getName() == $name) {
643
                return $method;
644
            }
645
        }
646
647
        return null;
648
    }
649
650
    /**
651
     * @param string $name Method name.
652
     *
653
     * @return mixed Generated return value based on the declared return value of the named method.
654
     */
655
    public function mockery_returnValueForMethod($name)
656
    {
657
        if (version_compare(PHP_VERSION, '7.0.0-dev') < 0) {
658
            return;
659
        }
660
661
        $rm = $this->mockery_getMethod($name);
662
        if (!$rm || !$rm->hasReturnType()) {
663
            return;
664
        }
665
666
        $type = (string) $rm->getReturnType();
667
        switch ($type) {
668
            case '':       return;
669
            case 'string': return '';
670
            case 'int':    return 0;
671
            case 'float':  return 0.0;
672
            case 'bool':   return false;
673
            case 'array':  return [];
674
675
            case 'callable':
676
            case 'Closure':
677
                return function () {
678
                };
679
680
            case 'Traversable':
681
            case 'Generator':
682
                // Remove eval() when minimum version >=5.5
683
                $generator = eval('return function () { yield; };');
684
                return $generator();
685
686
            case 'self':
687
                return \Mockery::mock($rm->getDeclaringClass()->getName());
688
689
            case 'void':
690
                return null;
691
692
            default:
693
                return \Mockery::mock($type);
694
        }
695
    }
696
697
    public function shouldHaveReceived($method = null, $args = null)
698
    {
699
        if ($method === null) {
700
            return new HigherOrderMessage($this, "shouldHaveReceived");
701
        }
702
703
        $expectation = new \Mockery\VerificationExpectation($this, $method);
704
        if (null !== $args) {
705
            $expectation->withArgs($args);
0 ignored issues
show
Documentation introduced by
$args is of type null, but the function expects a array|object<Closure>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
706
        }
707
        $expectation->atLeast()->once();
708
        $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
709
        $this->_mockery_expectations_count++;
710
        $director->verify();
711
        return $director;
712
    }
713
714
    public function shouldNotHaveReceived($method = null, $args = null)
715
    {
716
        if ($method === null) {
717
            return new HigherOrderMessage($this, "shouldNotHaveReceived");
718
        }
719
720
        $expectation = new \Mockery\VerificationExpectation($this, $method);
721
        if (null !== $args) {
722
            $expectation->withArgs($args);
0 ignored issues
show
Documentation introduced by
$args is of type null, but the function expects a array|object<Closure>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
723
        }
724
        $expectation->never();
725
        $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
726
        $this->_mockery_expectations_count++;
727
        $director->verify();
728
        return null;
729
    }
730
731
    protected static function _mockery_handleStaticMethodCall($method, array $args)
732
    {
733
        try {
734
            $associatedRealObject = \Mockery::fetchMock(__CLASS__);
735
            return $associatedRealObject->__call($method, $args);
736
        } catch (\BadMethodCallException $e) {
737
            throw new \BadMethodCallException(
738
                'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
739
                . '() does not exist on this mock object'
740
            );
741
        }
742
    }
743
744
    protected function _mockery_getReceivedMethodCalls()
745
    {
746
        return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
747
    }
748
749
    protected function _mockery_handleMethodCall($method, array $args)
750
    {
751
        $this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));
752
753
        $rm = $this->mockery_getMethod($method);
754
        if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
755
            if ($rm->isAbstract()) {
756
                return;
757
            }
758
759
            try {
760
                $prototype = $rm->getPrototype();
761
                if ($prototype->isAbstract()) {
762
                    return;
763
                }
764
            } catch (\ReflectionException $re) {
765
                // noop - there is no hasPrototype method
766
            }
767
768
            return call_user_func_array("parent::$method", $args);
769
        }
770
771
        if (isset($this->_mockery_expectations[$method])
772
        && !$this->_mockery_disableExpectationMatching) {
773
            $handler = $this->_mockery_expectations[$method];
774
775
            try {
776
                return $handler->call($args);
777
            } catch (\Mockery\Exception\NoMatchingExpectationException $e) {
778
                if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
779
                    throw $e;
780
                }
781
            }
782
        }
783
784
        if (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) {
785
            return call_user_func_array(array($this->_mockery_partial, $method), $args);
786
        } elseif ($this->_mockery_deferMissing && is_callable("parent::$method")
787
            && (!$this->hasMethodOverloadingInParentClass() || method_exists(get_parent_class($this), $method))) {
788
            return call_user_func_array("parent::$method", $args);
789
        } elseif ($method == '__toString') {
790
            // __toString is special because we force its addition to the class API regardless of the
791
            // original implementation.  Thus, we should always return a string rather than honor
792
            // _mockery_ignoreMissing and break the API with an error.
793
            return sprintf("%s#%s", __CLASS__, spl_object_hash($this));
794
        } elseif ($this->_mockery_ignoreMissing) {
795
            if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (method_exists($this->_mockery_partial, $method) || is_callable("parent::$method"))) {
796
                if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) {
797
                    return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args);
798
                } elseif (null === $this->_mockery_defaultReturnValue) {
799
                    return $this->mockery_returnValueForMethod($method);
800
                } else {
801
                    return $this->_mockery_defaultReturnValue;
802
                }
803
            }
804
        }
805
806
        $message = 'Method ' . __CLASS__ . '::' . $method .
807
            '() does not exist on this mock object';
808
809
        if (!is_null($rm)) {
810
            $message = 'Received ' . __CLASS__ .
811
                '::' . $method . '(), but no expectations were specified';
812
        }
813
814
        throw new \BadMethodCallException(
815
            $message
816
        );
817
    }
818
819
    /**
820
     * Uses reflection to get the list of all
821
     * methods within the current mock object
822
     *
823
     * @return array
824
     */
825
    protected function mockery_getMethods()
826
    {
827
        if (static::$_mockery_methods) {
828
            return static::$_mockery_methods;
829
        }
830
831
        if (isset($this->_mockery_partial)) {
832
            $reflected = new \ReflectionObject($this->_mockery_partial);
833
        } else {
834
            $reflected = new \ReflectionClass($this);
835
        }
836
837
        return static::$_mockery_methods = $reflected->getMethods();
0 ignored issues
show
Documentation Bug introduced by
It seems like $reflected->getMethods() of type array<integer,object<ReflectionMethod>> is incompatible with the declared type array<integer,object<Mockery\ReflectionMethod>> of property $_mockery_methods.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
838
    }
839
840
    private function hasMethodOverloadingInParentClass()
841
    {
842
        // if there's __call any name would be callable
843
        return is_callable('parent::' . uniqid(__FUNCTION__));
844
    }
845
846
    /**
847
     * @return array
848
     */
849
    private function getNonPublicMethods()
850
    {
851
        return array_map(
852
            function ($method) {
853
                return $method->getName();
854
            },
855
            array_filter($this->mockery_getMethods(), function ($method) {
856
                return !$method->isPublic();
857
            })
858
        );
859
    }
860
}
861