1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20:
21: namespace Mockery;
22:
23: use Mockery\MockInterface;
24:
25: class Mock implements MockInterface
26: {
27:
28: 29: 30: 31: 32:
33: protected $_mockery_expectations = array();
34:
35: 36: 37: 38: 39: 40:
41: protected $_mockery_ignoreMissing = false;
42:
43: 44: 45: 46: 47: 48:
49: protected $_mockery_deferMissing = false;
50:
51: 52: 53: 54: 55:
56: protected $_mockery_verified = false;
57:
58: 59: 60: 61: 62:
63: protected $_mockery_name = null;
64:
65: 66: 67: 68: 69:
70: protected $_mockery_allocatedOrder = 0;
71:
72: 73: 74: 75: 76:
77: protected $_mockery_currentOrder = 0;
78:
79: 80: 81: 82: 83:
84: protected $_mockery_groups = array();
85:
86: 87: 88: 89: 90:
91: protected $_mockery_container = null;
92:
93: 94: 95: 96: 97: 98: 99:
100: protected $_mockery_partial = null;
101:
102: 103: 104: 105: 106: 107: 108:
109: protected $_mockery_disableExpectationMatching = false;
110:
111: 112: 113: 114: 115: 116:
117: protected $_mockery_mockableProperties = array();
118:
119: 120: 121:
122: protected $_mockery_mockableMethods = array();
123:
124: 125: 126: 127: 128:
129: protected static $_mockery_methods;
130:
131: protected $_mockery_allowMockingProtectedMethods = false;
132:
133: protected $_mockery_receivedMethodCalls;
134:
135: 136: 137: 138:
139: protected $_mockery_defaultReturnValue = null;
140:
141: 142: 143: 144: 145: 146: 147: 148:
149: public function mockery_init(\Mockery\Container $container = null, $partialObject = null)
150: {
151: if(is_null($container)) {
152: $container = new \Mockery\Container;
153: }
154: $this->_mockery_container = $container;
155: if (!is_null($partialObject)) {
156: $this->_mockery_partial = $partialObject;
157: }
158:
159: if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
160: foreach ($this->mockery_getMethods() as $method) {
161: if ($method->isPublic() && !$method->isStatic()) $this->_mockery_mockableMethods[] = $method->getName();
162: }
163: }
164: }
165:
166: 167: 168: 169: 170: 171:
172: public function shouldReceive()
173: {
174:
175: $nonPublicMethods = $this->getNonPublicMethods();
176:
177: $self = $this;
178: $allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;
179:
180: $lastExpectation = \Mockery::parseShouldReturnArgs(
181: $this, func_get_args(), function ($method) use ($self, $nonPublicMethods, $allowMockingProtectedMethods) {
182: $rm = $self->mockery_getMethod($method);
183: if ($rm) {
184: if ($rm->isPrivate()) {
185: throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method");
186: }
187: if (!$allowMockingProtectedMethods && $rm->isProtected()) {
188: throw new \InvalidArgumentException("$method() cannot be mocked as it a protected method and mocking protected methods is not allowed for this mock");
189: }
190: }
191:
192: $director = $self->mockery_getExpectationsFor($method);
193: if (!$director) {
194: $director = new \Mockery\ExpectationDirector($method, $self);
195: $self->mockery_setExpectationsFor($method, $director);
196: }
197: $expectation = new \Mockery\Expectation($self, $method);
198: $director->addExpectation($expectation);
199: return $expectation;
200: }
201: );
202: return $lastExpectation;
203: }
204:
205: 206: 207: 208: 209:
210: public function shouldAllowMockingMethod($method)
211: {
212: $this->_mockery_mockableMethods[] = $method;
213: return $this;
214: }
215:
216: 217: 218: 219: 220:
221: public function shouldIgnoreMissing($returnValue = null)
222: {
223: $this->_mockery_ignoreMissing = true;
224: $this->_mockery_defaultReturnValue = $returnValue;
225: return $this;
226: }
227:
228: public function asUndefined()
229: {
230: $this->_mockery_ignoreMissing = true;
231: $this->_mockery_defaultReturnValue = new \Mockery\Undefined;
232: return $this;
233: }
234:
235: 236: 237:
238: public function shouldAllowMockingProtectedMethods()
239: {
240: $this->_mockery_allowMockingProtectedMethods = true;
241: return $this;
242: }
243:
244:
245: 246: 247: 248: 249: 250: 251: 252:
253: public function shouldDeferMissing()
254: {
255: $this->_mockery_deferMissing = true;
256: return $this;
257: }
258:
259: 260: 261: 262: 263:
264: public function makePartial()
265: {
266: return $this->shouldDeferMissing();
267: }
268:
269: 270: 271: 272: 273: 274: 275: 276: 277:
278: public function shouldExpect(\Closure $closure)
279: {
280: $recorder = new \Mockery\Recorder($this, $this->_mockery_partial);
281: $this->_mockery_disableExpectationMatching = true;
282: $closure($recorder);
283: $this->_mockery_disableExpectationMatching = false;
284: return $this;
285: }
286:
287: 288: 289: 290: 291: 292: 293:
294: public function byDefault()
295: {
296: foreach ($this->_mockery_expectations as $director) {
297: $exps = $director->getExpectations();
298: foreach ($exps as $exp) {
299: $exp->byDefault();
300: }
301: }
302: return $this;
303: }
304:
305: 306: 307:
308: public function __call($method, array $args)
309: {
310: return $this->_mockery_handleMethodCall($method, $args);
311: }
312:
313: public static function __callStatic($method, array $args)
314: {
315: return self::_mockery_handleStaticMethodCall($method, $args);
316: }
317:
318: 319: 320:
321: public function __toString()
322: {
323: return $this->__call('__toString', array());
324: }
325:
326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342:
343:
344: 345: 346: 347: 348: 349:
350: public function mockery_verify()
351: {
352: if ($this->_mockery_verified) return true;
353: if (isset($this->_mockery_ignoreVerification)
354: && $this->_mockery_ignoreVerification == true) {
355: return true;
356: }
357: $this->_mockery_verified = true;
358: foreach($this->_mockery_expectations as $director) {
359: $director->verify();
360: }
361: }
362:
363: 364: 365: 366: 367:
368: public function mockery_teardown()
369: {
370:
371: }
372:
373: 374: 375: 376: 377:
378: public function mockery_allocateOrder()
379: {
380: $this->_mockery_allocatedOrder += 1;
381: return $this->_mockery_allocatedOrder;
382: }
383:
384: 385: 386: 387: 388: 389:
390: public function mockery_setGroup($group, $order)
391: {
392: $this->_mockery_groups[$group] = $order;
393: }
394:
395: 396: 397: 398: 399:
400: public function mockery_getGroups()
401: {
402: return $this->_mockery_groups;
403: }
404:
405: 406: 407: 408: 409:
410: public function mockery_setCurrentOrder($order)
411: {
412: $this->_mockery_currentOrder = $order;
413: return $this->_mockery_currentOrder;
414: }
415:
416: 417: 418: 419: 420:
421: public function mockery_getCurrentOrder()
422: {
423: return $this->_mockery_currentOrder;
424: }
425:
426: 427: 428: 429: 430: 431: 432: 433:
434: public function mockery_validateOrder($method, $order)
435: {
436: if ($order < $this->_mockery_currentOrder) {
437: $exception = new \Mockery\Exception\InvalidOrderException(
438: 'Method ' . __CLASS__ . '::' . $method . '()'
439: . ' called out of order: expected order '
440: . $order . ', was ' . $this->_mockery_currentOrder
441: );
442: $exception->setMock($this)
443: ->setMethodName($method)
444: ->setExpectedOrder($order)
445: ->setActualOrder($this->_mockery_currentOrder);
446: throw $exception;
447: }
448: $this->mockery_setCurrentOrder($order);
449: }
450:
451: 452: 453: 454: 455:
456: public function mockery_getExpectationCount()
457: {
458: $count = 0;
459: foreach($this->_mockery_expectations as $director) {
460: $count += $director->getExpectationCount();
461: }
462: return $count;
463: }
464:
465: 466: 467: 468: 469: 470:
471: public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
472: {
473: $this->_mockery_expectations[$method] = $director;
474: }
475:
476: 477: 478: 479: 480: 481:
482: public function mockery_getExpectationsFor($method)
483: {
484: if (isset($this->_mockery_expectations[$method])) {
485: return $this->_mockery_expectations[$method];
486: }
487: }
488:
489: 490: 491: 492: 493: 494: 495:
496: public function mockery_findExpectation($method, array $args)
497: {
498: if (!isset($this->_mockery_expectations[$method])) {
499: return null;
500: }
501: $director = $this->_mockery_expectations[$method];
502:
503: return $director->findExpectation($args);
504: }
505:
506: 507: 508: 509: 510:
511: public function mockery_getContainer()
512: {
513: return $this->_mockery_container;
514: }
515:
516: 517: 518: 519: 520:
521: public function mockery_getName()
522: {
523: return __CLASS__;
524: }
525:
526: 527: 528:
529: public function mockery_getMockableProperties()
530: {
531: return $this->_mockery_mockableProperties;
532: }
533:
534: public function __isset($name)
535: {
536: if (false === stripos($name, '_mockery_') && method_exists(get_parent_class($this), '__isset')) {
537: return parent::__isset($name);
538: }
539: }
540:
541: public function mockery_getExpectations()
542: {
543: return $this->_mockery_expectations;
544: }
545:
546: 547: 548: 549: 550: 551: 552: 553: 554:
555: public function mockery_callSubjectMethod($name, array $args)
556: {
557: return call_user_func_array('parent::' . $name, $args);
558: }
559:
560: 561: 562:
563: public function mockery_getMockableMethods()
564: {
565: return $this->_mockery_mockableMethods;
566: }
567:
568: 569: 570:
571: public function mockery_isAnonymous()
572: {
573: $rfc = new \ReflectionClass($this);
574: return false === $rfc->getParentClass();
575: }
576:
577: public function __wakeup()
578: {
579: 580: 581: 582: 583: 584:
585: }
586:
587: public function mockery_getMethod($name)
588: {
589: foreach ($this->mockery_getMethods() as $method) {
590: if ($method->getName() == $name) {
591: return $method;
592: }
593: }
594:
595: return null;
596: }
597:
598: public function shouldHaveReceived($method, $args = null)
599: {
600: $expectation = new \Mockery\VerificationExpectation($this, $method);
601: if (null !== $args) {
602: $expectation->withArgs($args);
603: }
604: $expectation->atLeast()->once();
605: $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
606: $director->verify();
607: return $director;
608: }
609:
610: public function shouldNotHaveReceived($method, $args = null)
611: {
612: $expectation = new \Mockery\VerificationExpectation($this, $method);
613: if (null !== $args) {
614: $expectation->withArgs($args);
615: }
616: $expectation->never();
617: $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
618: $director->verify();
619: return null;
620: }
621:
622: protected static function _mockery_handleStaticMethodCall($method, array $args)
623: {
624: try {
625: $associatedRealObject = \Mockery::fetchMock(__CLASS__);
626: return $associatedRealObject->__call($method, $args);
627: } catch (\BadMethodCallException $e) {
628: throw new \BadMethodCallException(
629: 'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
630: . '() does not exist on this mock object'
631: );
632: }
633: }
634:
635: protected function _mockery_getReceivedMethodCalls()
636: {
637: return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
638: }
639:
640: protected function _mockery_handleMethodCall($method, array $args)
641: {
642: $this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));
643:
644: $rm = $this->mockery_getMethod($method);
645: if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
646: if ($rm->isAbstract()) {
647: return;
648: }
649:
650: try {
651: $prototype = $rm->getPrototype();
652: if ($prototype->isAbstract()) {
653: return;
654: }
655: } catch (\ReflectionException $re) {
656:
657: }
658:
659: return call_user_func_array("parent::$method", $args);
660: }
661:
662: if (isset($this->_mockery_expectations[$method])
663: && !$this->_mockery_disableExpectationMatching) {
664: $handler = $this->_mockery_expectations[$method];
665:
666: try {
667: return $handler->call($args);
668: } catch (\Mockery\Exception\NoMatchingExpectationException $e) {
669: if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
670: throw $e;
671: }
672: }
673: }
674:
675: if (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) {
676: return call_user_func_array(array($this->_mockery_partial, $method), $args);
677: } elseif ($this->_mockery_deferMissing && is_callable("parent::$method")) {
678: return call_user_func_array("parent::$method", $args);
679: } elseif ($method == '__toString') {
680:
681:
682:
683: return sprintf("%s#%s", __CLASS__, spl_object_hash($this));
684: } elseif ($this->_mockery_ignoreMissing) {
685: if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined)
686: return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args);
687: else
688: return $this->_mockery_defaultReturnValue;
689: }
690: throw new \BadMethodCallException(
691: 'Method ' . __CLASS__ . '::' . $method . '() does not exist on this mock object'
692: );
693: }
694:
695: protected function mockery_getMethods()
696: {
697: if (static::$_mockery_methods) {
698: return static::$_mockery_methods;
699: }
700:
701: $methods = array();
702:
703: if (isset($this->_mockery_partial)) {
704: $reflected = new \ReflectionObject($this->_mockery_partial);
705: $methods = $reflected->getMethods();
706: } else {
707: $reflected = new \ReflectionClass($this);
708: foreach ($reflected->getMethods() as $method) {
709: try {
710: $methods[] = $method->getPrototype();
711: } catch (\ReflectionException $re) {
712: 713: 714:
715: if ($method->isPrivate()) {
716: $methods[] = $method;
717: }
718: }
719: }
720: }
721:
722: return static::$_mockery_methods = $methods;
723: }
724:
725: 726: 727:
728: private function getNonPublicMethods()
729: {
730: return array_map(
731: function ($method) {
732: return $method->getName();
733: },
734: array_filter($this->mockery_getMethods(), function ($method) {
735: return !$method->isPublic();
736: })
737: );
738: }
739:
740: }
741: