Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
13.64% |
3 / 22 |
CRAP | |
28.80% |
53 / 184 |
| Container | |
0.00% |
0 / 1 |
|
13.64% |
3 / 22 |
2104.94 | |
28.80% |
53 / 184 |
| __construct(Generator $generator = null, LoaderInterface $loader = null) | |
100.00% |
1 / 1 |
3 | |
100.00% |
3 / 3 |
|||
| mock() | |
0.00% |
0 / 1 |
403.65 | |
36.73% |
36 / 98 |
|||
| instanceMock() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getLoader() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getGenerator() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| mockery_teardown() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| mockery_verify() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
| mockery_close() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| mockery_allocateOrder() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| mockery_setGroup($group, $order) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| mockery_getGroups() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| mockery_setCurrentOrder($order) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| mockery_getCurrentOrder() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| mockery_validateOrder($method, $order, \Mockery\MockInterface $mock) | |
0.00% |
0 / 1 |
5.08 | |
8.33% |
1 / 12 |
|||
| mockery_getExpectationCount() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| rememberMock(\Mockery\MockInterface $mock) | |
0.00% |
0 / 1 |
2.03 | |
80.00% |
4 / 5 |
|||
| self() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| fetchMock($reference) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 2 |
|||
| _getInstance($mockName, $constructorArgs = null) | |
0.00% |
0 / 1 |
4.12 | |
50.00% |
4 / 8 |
|||
| declareClass($fqcn) | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 4 |
|||
| anonymous function ($part) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| checkForNamedMockClashes($config) | |
0.00% |
0 / 1 |
10.15 | |
27.27% |
3 / 11 |
|||
| <?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 | |
| */ | |
| namespace Mockery; | |
| use Mockery\Generator\Generator; | |
| use Mockery\Generator\MockConfigurationBuilder; | |
| use Mockery\Loader\Loader as LoaderInterface; | |
| class Container | |
| { | |
| const BLOCKS = \Mockery::BLOCKS; | |
| /** | |
| * Store of mock objects | |
| * | |
| * @var array | |
| */ | |
| protected $_mocks = array(); | |
| /** | |
| * Order number of allocation | |
| * | |
| * @var int | |
| */ | |
| protected $_allocatedOrder = 0; | |
| /** | |
| * Current ordered number | |
| * | |
| * @var int | |
| */ | |
| protected $_currentOrder = 0; | |
| /** | |
| * Ordered groups | |
| * | |
| * @var array | |
| */ | |
| protected $_groups = array(); | |
| /** | |
| * @var Generator\Generator | |
| */ | |
| protected $_generator; | |
| /** | |
| * @var LoaderInterface | |
| */ | |
| protected $_loader; | |
| /** | |
| * @var array | |
| */ | |
| protected $_namedMocks = array(); | |
| public function __construct(Generator $generator = null, LoaderInterface $loader = null) | |
| { | |
| $this->_generator = $generator ?: \Mockery::getDefaultGenerator(); | |
| $this->_loader = $loader ?: \Mockery::getDefaultLoader(); | |
| } | |
| /** | |
| * Generates a new mock object for this container | |
| * | |
| * I apologies in advance for this. A God Method just fits the API which | |
| * doesn't require differentiating between classes, interfaces, abstracts, | |
| * names or partials - just so long as it's something that can be mocked. | |
| * I'll refactor it one day so it's easier to follow. | |
| * | |
| * @return \Mockery\Mock | |
| */ | |
| public function mock() | |
| { | |
| $expectationClosure = null; | |
| $quickdefs = array(); | |
| $constructorArgs = null; | |
| $blocks = array(); | |
| $args = func_get_args(); | |
| if (count($args) > 1) { | |
| $finalArg = end($args); | |
| reset($args); | |
| if (is_callable($finalArg) && is_object($finalArg)) { | |
| $expectationClosure = array_pop($args); | |
| } | |
| } | |
| $builder = new MockConfigurationBuilder(); | |
| foreach ($args as $k => $arg) { | |
| if ($arg instanceof MockConfigurationBuilder) { | |
| $builder = $arg; | |
| unset($args[$k]); | |
| } | |
| } | |
| reset($args); | |
| $builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps()); | |
| while (count($args) > 0) { | |
| $arg = current($args); | |
| // check for multiple interfaces | |
| if (is_string($arg) && strpos($arg, ',') && !strpos($arg, ']')) { | |
| $interfaces = explode(',', str_replace(' ', '', $arg)); | |
| foreach ($interfaces as $i) { | |
| if (!interface_exists($i, true) && !class_exists($i, true)) { | |
| throw new \Mockery\Exception( | |
| 'Class name follows the format for defining multiple' | |
| . ' interfaces, however one or more of the interfaces' | |
| . ' do not exist or are not included, or the base class' | |
| . ' (which you may omit from the mock definition) does not exist' | |
| ); | |
| } | |
| } | |
| $builder->addTargets($interfaces); | |
| array_shift($args); | |
| continue; | |
| } elseif (is_string($arg) && substr($arg, 0, 6) == 'alias:') { | |
| $name = array_shift($args); | |
| $name = str_replace('alias:', '', $name); | |
| $builder->addTarget('stdClass'); | |
| $builder->setName($name); | |
| continue; | |
| } elseif (is_string($arg) && substr($arg, 0, 9) == 'overload:') { | |
| $name = array_shift($args); | |
| $name = str_replace('overload:', '', $name); | |
| $builder->setInstanceMock(true); | |
| $builder->addTarget('stdClass'); | |
| $builder->setName($name); | |
| continue; | |
| } elseif (is_string($arg) && substr($arg, strlen($arg)-1, 1) == ']') { | |
| $parts = explode('[', $arg); | |
| if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) { | |
| throw new \Mockery\Exception('Can only create a partial mock from' | |
| . ' an existing class or interface'); | |
| } | |
| $class = $parts[0]; | |
| $parts[1] = str_replace(' ','', $parts[1]); | |
| $partialMethods = explode(',', strtolower(rtrim($parts[1], ']'))); | |
| $builder->addTarget($class); | |
| $builder->setWhiteListedMethods($partialMethods); | |
| array_shift($args); | |
| continue; | |
| } elseif (is_string($arg) && (class_exists($arg, true) || interface_exists($arg, true))) { | |
| $class = array_shift($args); | |
| $builder->addTarget($class); | |
| continue; | |
| } elseif (is_string($arg)) { | |
| $class = array_shift($args); | |
| $builder->addTarget($class); | |
| continue; | |
| } elseif (is_object($arg)) { | |
| $partial = array_shift($args); | |
| $builder->addTarget($partial); | |
| continue; | |
| } elseif (is_array($arg) && !empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) { | |
| // if associative array | |
| if(array_key_exists(self::BLOCKS, $arg)) $blocks = $arg[self::BLOCKS]; unset($arg[self::BLOCKS]); | |
| $quickdefs = array_shift($args); | |
| continue; | |
| } elseif (is_array($arg)) { | |
| $constructorArgs = array_shift($args); | |
| continue; | |
| } | |
| throw new \Mockery\Exception( | |
| 'Unable to parse arguments sent to ' | |
| . get_class($this) . '::mock()' | |
| ); | |
| } | |
| $builder->addBlackListedMethods($blocks); | |
| if (!is_null($constructorArgs)) { | |
| $builder->addBlackListedMethod("__construct"); // we need to pass through | |
| } | |
| if (!empty($partialMethods) && $constructorArgs === null) { | |
| $constructorArgs = array(); | |
| } | |
| $config = $builder->getMockConfiguration(); | |
| $this->checkForNamedMockClashes($config); | |
| $def = $this->getGenerator()->generate($config); | |
| if (class_exists($def->getClassName(), $attemptAutoload = false)) { | |
| $rfc = new \ReflectionClass($def->getClassName()); | |
| if (!$rfc->implementsInterface("Mockery\MockInterface")) { | |
| throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists"); | |
| } | |
| } | |
| $this->getLoader()->load($def); | |
| $mock = $this->_getInstance($def->getClassName(), $constructorArgs); | |
| $mock->mockery_init($this, $config->getTargetObject()); | |
| if (!empty($quickdefs)) { | |
| $mock->shouldReceive($quickdefs)->byDefault(); | |
| } | |
| if (!empty($expectationClosure)) { | |
| $expectationClosure($mock); | |
| } | |
| $this->rememberMock($mock); | |
| return $mock; | |
| } | |
| public function instanceMock() | |
| { | |
| } | |
| public function getLoader() | |
| { | |
| return $this->_loader; | |
| } | |
| public function getGenerator() | |
| { | |
| return $this->_generator; | |
| } | |
| /** | |
| * Tear down tasks for this container | |
| * | |
| * @return void | |
| */ | |
| public function mockery_teardown() | |
| { | |
| try { | |
| $this->mockery_verify(); | |
| } catch (\Exception $e) { | |
| $this->mockery_close(); | |
| throw $e; | |
| } | |
| } | |
| /** | |
| * Verify the container mocks | |
| * | |
| * @return void | |
| */ | |
| public function mockery_verify() | |
| { | |
| foreach($this->_mocks as $mock) { | |
| $mock->mockery_verify(); | |
| } | |
| } | |
| /** | |
| * Reset the container to its original state | |
| * | |
| * @return void | |
| */ | |
| public function mockery_close() | |
| { | |
| foreach($this->_mocks as $mock) { | |
| $mock->mockery_teardown(); | |
| } | |
| $this->_mocks = array(); | |
| } | |
| /** | |
| * Fetch the next available allocation order number | |
| * | |
| * @return int | |
| */ | |
| public function mockery_allocateOrder() | |
| { | |
| $this->_allocatedOrder += 1; | |
| return $this->_allocatedOrder; | |
| } | |
| /** | |
| * Set ordering for a group | |
| * | |
| * @param mixed $group | |
| * @param int $order | |
| */ | |
| public function mockery_setGroup($group, $order) | |
| { | |
| $this->_groups[$group] = $order; | |
| } | |
| /** | |
| * Fetch array of ordered groups | |
| * | |
| * @return array | |
| */ | |
| public function mockery_getGroups() | |
| { | |
| return $this->_groups; | |
| } | |
| /** | |
| * Set current ordered number | |
| * | |
| * @param int $order | |
| * @return int The current order number that was set | |
| */ | |
| public function mockery_setCurrentOrder($order) | |
| { | |
| $this->_currentOrder = $order; | |
| return $this->_currentOrder; | |
| } | |
| /** | |
| * Get current ordered number | |
| * | |
| * @return int | |
| */ | |
| public function mockery_getCurrentOrder() | |
| { | |
| return $this->_currentOrder; | |
| } | |
| /** | |
| * Validate the current mock's ordering | |
| * | |
| * @param string $method | |
| * @param int $order | |
| * @throws \Mockery\Exception | |
| * @return void | |
| */ | |
| public function mockery_validateOrder($method, $order, \Mockery\MockInterface $mock) | |
| { | |
| if ($order < $this->_currentOrder) { | |
| $exception = new \Mockery\Exception\InvalidOrderException( | |
| 'Method ' . $method . ' called out of order: expected order ' | |
| . $order . ', was ' . $this->_currentOrder | |
| ); | |
| $exception->setMock($mock) | |
| ->setMethodName($method) | |
| ->setExpectedOrder($order) | |
| ->setActualOrder($this->_currentOrder); | |
| throw $exception; | |
| } | |
| $this->mockery_setCurrentOrder($order); | |
| } | |
| /** | |
| * Gets the count of expectations on the mocks | |
| * | |
| * @return int | |
| */ | |
| public function mockery_getExpectationCount() | |
| { | |
| $count = 0; | |
| foreach($this->_mocks as $mock) { | |
| $count += $mock->mockery_getExpectationCount(); | |
| } | |
| return $count; | |
| } | |
| /** | |
| * Store a mock and set its container reference | |
| * | |
| * @param \Mockery\Mock | |
| * @return \Mockery\Mock | |
| */ | |
| public function rememberMock(\Mockery\MockInterface $mock) | |
| { | |
| if (!isset($this->_mocks[get_class($mock)])) { | |
| $this->_mocks[get_class($mock)] = $mock; | |
| } else { | |
| /** | |
| * This condition triggers for an instance mock where origin mock | |
| * is already remembered | |
| */ | |
| $this->_mocks[] = $mock; | |
| } | |
| return $mock; | |
| } | |
| /** | |
| * Retrieve the last remembered mock object, which is the same as saying | |
| * retrieve the current mock being programmed where you have yet to call | |
| * mock() to change it - thus why the method name is "self" since it will be | |
| * be used during the programming of the same mock. | |
| * | |
| * @return \Mockery\Mock | |
| */ | |
| public function self() | |
| { | |
| $mocks = array_values($this->_mocks); | |
| $index = count($mocks) - 1; | |
| return $mocks[$index]; | |
| } | |
| /** | |
| * Return a specific remembered mock according to the array index it | |
| * was stored to in this container instance | |
| * | |
| * @return \Mockery\Mock | |
| */ | |
| public function fetchMock($reference) | |
| { | |
| if (isset($this->_mocks[$reference])) return $this->_mocks[$reference]; | |
| } | |
| protected function _getInstance($mockName, $constructorArgs = null) | |
| { | |
| $r = new \ReflectionClass($mockName); | |
| if (null === $r->getConstructor()) { | |
| $return = new $mockName; | |
| return $return; | |
| } | |
| if ($constructorArgs !== null) { | |
| return $r->newInstanceArgs($constructorArgs); | |
| } | |
| $return = unserialize(sprintf('O:%d:"%s":0:{}', strlen($mockName), $mockName)); | |
| return $return; | |
| } | |
| /** | |
| * Takes a class name and declares it | |
| * | |
| * @param string $fqcn | |
| */ | |
| public function declareClass($fqcn) | |
| { | |
| if (false !== strpos($fqcn, '/')) { | |
| throw new \Mockery\Exception( | |
| 'Class name contains a forward slash instead of backslash needed ' | |
| . 'when employing namespaces' | |
| ); | |
| } | |
| if (false !== strpos($fqcn, "\\")) { | |
| $parts = array_filter(explode("\\", $fqcn), function ($part) { | |
| return $part !== ""; | |
| }); | |
| $cl = array_pop($parts); | |
| $ns = implode("\\", $parts); | |
| eval(" namespace $ns { class $cl {} }"); | |
| } else { | |
| eval(" class $fqcn {} "); | |
| } | |
| } | |
| protected function checkForNamedMockClashes($config) | |
| { | |
| $name = $config->getName(); | |
| if (!$name) { | |
| return; | |
| } | |
| $hash = $config->getHash(); | |
| if (isset($this->_namedMocks[$name])) { | |
| if ($hash !== $this->_namedMocks[$name]) { | |
| throw new \Mockery\Exception( | |
| "The mock named '$name' has been already defined with a different mock configuration" | |
| ); | |
| } | |
| } | |
| $this->_namedMocks[$name] = $hash; | |
| } | |
| } |