Viewing file: Mockery.php (18.98 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /** * Mockery * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://github.com/padraic/mockery/blob/master/LICENSE * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to padraic@php.net so we can send you a copy immediately. * * @category Mockery * @package Mockery * @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com) * @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License */
use Mockery\ExpectationInterface; use Mockery\Generator\CachingGenerator; use Mockery\Generator\Generator; use Mockery\Generator\MockConfigurationBuilder; use Mockery\Generator\StringManipulationGenerator; use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass; use Mockery\Generator\StringManipulation\Pass\ClassNamePass; use Mockery\Generator\StringManipulation\Pass\ClassPass; use Mockery\Generator\StringManipulation\Pass\InstanceMockPass; use Mockery\Generator\StringManipulation\Pass\InterfacePass; use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass; use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass; use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass; use Mockery\Loader\EvalLoader; use Mockery\Loader\Loader;
class Mockery { const BLOCKS = 'Mockery_Forward_Blocks';
/** * Global container to hold all mocks for the current unit test running. * * @var \Mockery\Container */ protected static $_container = null;
/** * Global configuration handler containing configuration options. * * @var \Mockery\Configuration */ protected static $_config = null;
/** * @var \Mockery\Generator\Generator */ protected static $_generator;
/** * @var \Mockery\Loader\Loader */ protected static $_loader;
/** * Static shortcut to \Mockery\Container::mock(). * * @return \Mockery\MockInterface */ public static function mock() { $args = func_get_args();
return call_user_func_array(array(self::getContainer(), 'mock'), $args); }
/** * @return \Mockery\MockInterface */ public static function spy() { $args = func_get_args(); return call_user_func_array(array(self::getContainer(), 'mock'), $args)->shouldIgnoreMissing(); }
/** * @return \Mockery\MockInterface */ public static function instanceMock() { $args = func_get_args();
return call_user_func_array(array(self::getContainer(), 'mock'), $args); }
/** * Static shortcut to \Mockery\Container::mock(), first argument names the mock. * * @return \Mockery\MockInterface */ public static function namedMock() { $args = func_get_args(); $name = array_shift($args);
$builder = new MockConfigurationBuilder(); $builder->setName($name);
array_unshift($args, $builder);
return call_user_func_array(array(self::getContainer(), 'mock'), $args); }
/** * Static shortcut to \Mockery\Container::self(). * * @throws LogicException * * @return \Mockery\MockInterface */ public static function self() { if (is_null(self::$_container)) { throw new \LogicException('You have not declared any mocks yet'); }
return self::$_container->self(); }
/** * Static shortcut to closing up and verifying all mocks in the global * container, and resetting the container static variable to null. * * @return void */ public static function close() { if (is_null(self::$_container)) { return; }
self::$_container->mockery_teardown(); self::$_container->mockery_close(); self::$_container = null; }
/** * Static fetching of a mock associated with a name or explicit class poser. * * @param $name * * @return \Mockery\Mock */ public static function fetchMock($name) { return self::$_container->fetchMock($name); }
/** * Get the container. */ public static function getContainer() { if (is_null(self::$_container)) { self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader()); }
return self::$_container; }
/** * @param \Mockery\Generator\Generator $generator */ public static function setGenerator(Generator $generator) { self::$_generator = $generator; }
public static function getGenerator() { if (is_null(self::$_generator)) { self::$_generator = self::getDefaultGenerator(); }
return self::$_generator; }
public static function getDefaultGenerator() { $generator = new StringManipulationGenerator(array( new CallTypeHintPass(), new ClassPass(), new ClassNamePass(), new InstanceMockPass(), new InterfacePass(), new MethodDefinitionPass(), new RemoveUnserializeForInternalSerializableClassesPass(), new RemoveBuiltinMethodsThatAreFinalPass(), ));
return new CachingGenerator($generator); }
/** * @param Loader $loader */ public static function setLoader(Loader $loader) { self::$_loader = $loader; }
/** * @return Loader */ public static function getLoader() { if (is_null(self::$_loader)) { self::$_loader = self::getDefaultLoader(); }
return self::$_loader; }
/** * @return EvalLoader */ public static function getDefaultLoader() { return new EvalLoader(); }
/** * Set the container. * * @param \Mockery\Container $container * * @return \Mockery\Container */ public static function setContainer(Mockery\Container $container) { return self::$_container = $container; }
/** * Reset the container to null. */ public static function resetContainer() { self::$_container = null; }
/** * Return instance of ANY matcher. * * @return \Mockery\Matcher\Any */ public static function any() { return new \Mockery\Matcher\Any(); }
/** * Return instance of TYPE matcher. * * @param $expected * * @return \Mockery\Matcher\Type */ public static function type($expected) { return new \Mockery\Matcher\Type($expected); }
/** * Return instance of DUCKTYPE matcher. * * @return \Mockery\Matcher\Ducktype */ public static function ducktype() { return new \Mockery\Matcher\Ducktype(func_get_args()); }
/** * Return instance of SUBSET matcher. * * @param array $part * * @return \Mockery\Matcher\Subset */ public static function subset(array $part) { return new \Mockery\Matcher\Subset($part); }
/** * Return instance of CONTAINS matcher. * * @return \Mockery\Matcher\Contains */ public static function contains() { return new \Mockery\Matcher\Contains(func_get_args()); }
/** * Return instance of HASKEY matcher. * * @param $key * * @return \Mockery\Matcher\HasKey */ public static function hasKey($key) { return new \Mockery\Matcher\HasKey($key); }
/** * Return instance of HASVALUE matcher. * * @param $val * * @return \Mockery\Matcher\HasValue */ public static function hasValue($val) { return new \Mockery\Matcher\HasValue($val); }
/** * Return instance of CLOSURE matcher. * * @param $closure * * @return \Mockery\Matcher\Closure */ public static function on($closure) { return new \Mockery\Matcher\Closure($closure); }
/** * Return instance of MUSTBE matcher. * * @param $expected * * @return \Mockery\Matcher\MustBe */ public static function mustBe($expected) { return new \Mockery\Matcher\MustBe($expected); }
/** * Return instance of NOT matcher. * * @param $expected * * @return \Mockery\Matcher\Not */ public static function not($expected) { return new \Mockery\Matcher\Not($expected); }
/** * Return instance of ANYOF matcher. * * @return \Mockery\Matcher\AnyOf */ public static function anyOf() { return new \Mockery\Matcher\AnyOf(func_get_args()); }
/** * Return instance of NOTANYOF matcher. * * @return \Mockery\Matcher\NotAnyOf */ public static function notAnyOf() { return new \Mockery\Matcher\NotAnyOf(func_get_args()); }
/** * Get the global configuration container. */ public static function getConfiguration() { if (is_null(self::$_config)) { self::$_config = new \Mockery\Configuration(); }
return self::$_config; }
/** * Utility method to format method name and arguments into a string. * * @param string $method * @param array $arguments * * @return string */ public static function formatArgs($method, array $arguments = null) { if (is_null($arguments)) { return $method . '()'; }
$formattedArguments = array(); foreach ($arguments as $argument) { $formattedArguments[] = self::formatArgument($argument); }
return $method . '(' . implode(', ', $formattedArguments) . ')'; }
private static function formatArgument($argument, $depth = 0) { if (is_object($argument)) { return 'object(' . get_class($argument) . ')'; }
if (is_int($argument) || is_float($argument)) { return $argument; }
if (is_array($argument)) { if ($depth === 1) { $argument = 'array(...)'; } else { $sample = array(); foreach ($argument as $key => $value) { $sample[$key] = self::formatArgument($value, $depth + 1); } $argument = preg_replace("{\s}", '', var_export($sample, true)); }
return ((strlen($argument) > 1000) ? substr($argument, 0, 1000).'...)' : $argument); }
if (is_bool($argument)) { return $argument ? 'true' : 'false'; }
if (is_resource($argument)) { return 'resource(...)'; }
if (is_null($argument)) { return 'NULL'; }
$argument = (string) $argument;
return $depth === 0 ? '"' . $argument . '"' : $argument; }
/** * Utility function to format objects to printable arrays. * * @param array $objects * * @return string */ public static function formatObjects(array $objects = null) { static $formatting;
if ($formatting) { return '[Recursion]'; }
if (is_null($objects)) { return ''; }
$objects = array_filter($objects, 'is_object'); if (empty($objects)) { return ''; }
$formatting = true; $parts = array();
foreach ($objects as $object) { $parts[get_class($object)] = self::objectToArray($object); }
$formatting = false;
return 'Objects: ( ' . var_export($parts, true) . ')'; }
/** * Utility function to turn public properties and public get* and is* method values into an array. * * @param $object * @param int $nesting * * @return array */ private static function objectToArray($object, $nesting = 3) { if ($nesting == 0) { return array('...'); }
return array( 'class' => get_class($object), 'properties' => self::extractInstancePublicProperties($object, $nesting), 'getters' => self::extractGetters($object, $nesting) ); }
/** * Returns all public instance properties. * * @param $object * @param $nesting * * @return array */ private static function extractInstancePublicProperties($object, $nesting) { $reflection = new \ReflectionClass(get_class($object)); $properties = $reflection->getProperties(\ReflectionProperty::IS_PUBLIC); $cleanedProperties = array();
foreach ($properties as $publicProperty) { if (!$publicProperty->isStatic()) { $name = $publicProperty->getName(); $cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting); } }
return $cleanedProperties; }
/** * Returns all object getters. * * @param $object * @param $nesting * * @return array */ private static function extractGetters($object, $nesting) { $reflection = new \ReflectionClass(get_class($object)); $publicMethods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); $getters = array();
foreach ($publicMethods as $publicMethod) { $name = $publicMethod->getName(); $irrelevantName = (substr($name, 0, 3) !== 'get' && substr($name, 0, 2) !== 'is'); $isStatic = $publicMethod->isStatic(); $numberOfParameters = $publicMethod->getNumberOfParameters();
if ($irrelevantName || $numberOfParameters != 0 || $isStatic) { continue; }
try { $getters[$name] = self::cleanupNesting($object->$name(), $nesting); } catch (\Exception $e) { $getters[$name] = '!! ' . get_class($e) . ': ' . $e->getMessage() . ' !!'; } }
return $getters; }
private static function cleanupNesting($argument, $nesting) { if (is_object($argument)) { $object = self::objectToArray($argument, $nesting - 1); $object['class'] = get_class($argument);
return $object; }
if (is_array($argument)) { return self::cleanupArray($argument, $nesting - 1); }
return $argument; }
private static function cleanupArray($argument, $nesting = 3) { if ($nesting == 0) { return '...'; }
foreach ($argument as $key => $value) { if (is_array($value)) { $argument[$key] = self::cleanupArray($value, $nesting - 1); } elseif (is_object($value)) { $argument[$key] = self::objectToArray($value, $nesting - 1); } }
return $argument; }
/** * Utility function to parse shouldReceive() arguments and generate * expectations from such as needed. * * @param Mockery\MockInterface $mock * @param array $args * @param callable $add * @return \Mockery\CompositeExpectation */ public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add) { $composite = new \Mockery\CompositeExpectation();
foreach ($args as $arg) { if (is_array($arg)) { foreach ($arg as $k => $v) { $expectation = self::buildDemeterChain($mock, $k, $add)->andReturn($v); $composite->add($expectation); } } elseif (is_string($arg)) { $expectation = self::buildDemeterChain($mock, $arg, $add); $composite->add($expectation); } }
return $composite; }
/** * Sets up expectations on the members of the CompositeExpectation and * builds up any demeter chain that was passed to shouldReceive. * * @param \Mockery\MockInterface $mock * @param string $arg * @param callable $add * @throws Mockery\Exception * @return \Mockery\ExpectationDirector */ protected static function buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add) { /** @var Mockery\Container $container */ $container = $mock->mockery_getContainer(); $methodNames = explode('->', $arg); reset($methodNames);
if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() && !$mock->mockery_isAnonymous() && !in_array(current($methodNames), $mock->mockery_getMockableMethods()) ) { throw new \Mockery\Exception( 'Mockery\'s configuration currently forbids mocking the method ' . current($methodNames) . ' as it does not exist on the class or object ' . 'being mocked' ); }
/** @var ExpectationInterface|null $expectations */ $expectations = null;
/** @var Callable $nextExp */ $nextExp = function ($method) use ($add) { return $add($method); };
while (true) { $method = array_shift($methodNames); $expectations = $mock->mockery_getExpectationsFor($method);
if (is_null($expectations) || self::noMoreElementsInChain($methodNames)) { $expectations = $nextExp($method); if (self::noMoreElementsInChain($methodNames)) { break; }
$mock = self::getNewDemeterMock($container, $method, $expectations); } else { $demeterMockKey = $container->getKeyOfDemeterMockFor($method); if ($demeterMockKey) { $mock = self::getExistingDemeterMock($container, $demeterMockKey); } }
$nextExp = function ($n) use ($mock) { return $mock->shouldReceive($n); }; }
return $expectations; }
/** * @param \Mockery\Container $container * @param string $method * @param Mockery\ExpectationInterface $exp * * @return \Mockery\Mock */ private static function getNewDemeterMock(Mockery\Container $container, $method, Mockery\ExpectationInterface $exp ) { $mock = $container->mock('demeter_' . $method); $exp->andReturn($mock);
return $mock; }
/** * @param \Mockery\Container $container * @param string $demeterMockKey * * @return mixed */ private static function getExistingDemeterMock(Mockery\Container $container, $demeterMockKey) { $mocks = $container->getMocks(); $mock = $mocks[$demeterMockKey];
return $mock; }
/** * @param array $methodNames * * @return bool */ private static function noMoreElementsInChain(array $methodNames) { return empty($methodNames); } }
|