Primo Committ

This commit is contained in:
paoloar77
2024-05-07 12:17:25 +02:00
commit e73d0e5113
7204 changed files with 884387 additions and 0 deletions

View File

@@ -0,0 +1,983 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
use Mockery\ClosureWrapper;
use Mockery\ExpectationInterface;
use Mockery\Generator\CachingGenerator;
use Mockery\Generator\Generator;
use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Generator\MockNameBuilder;
use Mockery\Generator\StringManipulationGenerator;
use Mockery\Loader\EvalLoader;
use Mockery\Loader\Loader;
use Mockery\Matcher\MatcherAbstract;
use Mockery\Reflector;
class Mockery
{
const BLOCKS = 'Mockery_Forward_Blocks';
/**
* Global container to hold all mocks for the current unit test running.
*
* @var \Mockery\Container|null
*/
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;
/**
* @var array
*/
private static $_filesToCleanUp = [];
/**
* Defines the global helper functions
*
* @return void
*/
public static function globalHelpers()
{
require_once __DIR__ . '/helpers.php';
}
/**
* @return array
*
* @deprecated since 1.3.2 and will be removed in 2.0.
*/
public static function builtInTypes()
{
return array(
'array',
'bool',
'callable',
'float',
'int',
'iterable',
'object',
'self',
'string',
'void',
);
}
/**
* @param string $type
* @return bool
*
* @deprecated since 1.3.2 and will be removed in 2.0.
*/
public static function isBuiltInType($type)
{
return in_array($type, \Mockery::builtInTypes());
}
/**
* Static shortcut to \Mockery\Container::mock().
*
* @param mixed ...$args
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public static function mock(...$args)
{
return call_user_func_array(array(self::getContainer(), 'mock'), $args);
}
/**
* Static and semantic shortcut for getting a mock from the container
* and applying the spy's expected behavior into it.
*
* @param mixed ...$args
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public static function spy(...$args)
{
if (count($args) && $args[0] instanceof \Closure) {
$args[0] = new ClosureWrapper($args[0]);
}
return call_user_func_array(array(self::getContainer(), 'mock'), $args)->shouldIgnoreMissing();
}
/**
* Static and Semantic shortcut to \Mockery\Container::mock().
*
* @param mixed ...$args
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public static function instanceMock(...$args)
{
return call_user_func_array(array(self::getContainer(), 'mock'), $args);
}
/**
* Static shortcut to \Mockery\Container::mock(), first argument names the mock.
*
* @param mixed ...$args
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public static function namedMock(...$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|\Mockery\LegacyMockInterface
*/
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()
{
foreach (self::$_filesToCleanUp as $fileName) {
@unlink($fileName);
}
self::$_filesToCleanUp = [];
if (is_null(self::$_container)) {
return;
}
$container = self::$_container;
self::$_container = null;
$container->mockery_teardown();
$container->mockery_close();
}
/**
* Static fetching of a mock associated with a name or explicit class poser.
*
* @param string $name
*
* @return \Mockery\Mock
*/
public static function fetchMock($name)
{
return self::getContainer()->fetchMock($name);
}
/**
* Lazy loader and getter for
* the container property.
*
* @return Mockery\Container
*/
public static function getContainer()
{
if (is_null(self::$_container)) {
self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader());
}
return self::$_container;
}
/**
* Setter for the $_generator static property.
*
* @param \Mockery\Generator\Generator $generator
*/
public static function setGenerator(Generator $generator)
{
self::$_generator = $generator;
}
/**
* Lazy loader method and getter for
* the generator property.
*
* @return Generator
*/
public static function getGenerator()
{
if (is_null(self::$_generator)) {
self::$_generator = self::getDefaultGenerator();
}
return self::$_generator;
}
/**
* Creates and returns a default generator
* used inside this class.
*
* @return CachingGenerator
*/
public static function getDefaultGenerator()
{
return new CachingGenerator(StringManipulationGenerator::withDefaultPasses());
}
/**
* Setter for the $_loader static property.
*
* @param Loader $loader
*/
public static function setLoader(Loader $loader)
{
self::$_loader = $loader;
}
/**
* Lazy loader method and getter for
* the $_loader property.
*
* @return Loader
*/
public static function getLoader()
{
if (is_null(self::$_loader)) {
self::$_loader = self::getDefaultLoader();
}
return self::$_loader;
}
/**
* Gets an EvalLoader to be used as default.
*
* @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.
*
* @return void
*/
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 AndAnyOtherArgs matcher.
*
* An alternative name to `andAnyOtherArgs` so
* the API stays closer to `any` as well.
*
* @return \Mockery\Matcher\AndAnyOtherArgs
*/
public static function andAnyOthers()
{
return new \Mockery\Matcher\AndAnyOtherArgs();
}
/**
* Return instance of AndAnyOtherArgs matcher.
*
* @return \Mockery\Matcher\AndAnyOtherArgs
*/
public static function andAnyOtherArgs()
{
return new \Mockery\Matcher\AndAnyOtherArgs();
}
/**
* Return instance of TYPE matcher.
*
* @param mixed $expected
*
* @return \Mockery\Matcher\Type
*/
public static function type($expected)
{
return new \Mockery\Matcher\Type($expected);
}
/**
* Return instance of DUCKTYPE matcher.
*
* @param array ...$args
*
* @return \Mockery\Matcher\Ducktype
*/
public static function ducktype(...$args)
{
return new \Mockery\Matcher\Ducktype($args);
}
/**
* Return instance of SUBSET matcher.
*
* @param array $part
* @param bool $strict - (Optional) True for strict comparison, false for loose
*
* @return \Mockery\Matcher\Subset
*/
public static function subset(array $part, $strict = true)
{
return new \Mockery\Matcher\Subset($part, $strict);
}
/**
* Return instance of CONTAINS matcher.
*
* @param mixed $args
*
* @return \Mockery\Matcher\Contains
*/
public static function contains(...$args)
{
return new \Mockery\Matcher\Contains($args);
}
/**
* Return instance of HASKEY matcher.
*
* @param mixed $key
*
* @return \Mockery\Matcher\HasKey
*/
public static function hasKey($key)
{
return new \Mockery\Matcher\HasKey($key);
}
/**
* Return instance of HASVALUE matcher.
*
* @param mixed $val
*
* @return \Mockery\Matcher\HasValue
*/
public static function hasValue($val)
{
return new \Mockery\Matcher\HasValue($val);
}
/**
* Return instance of CLOSURE matcher.
*
* @param $reference
*
* @return \Mockery\Matcher\Closure
*/
public static function capture(&$reference)
{
$closure = function ($argument) use (&$reference) {
$reference = $argument;
return true;
};
return new \Mockery\Matcher\Closure($closure);
}
/**
* Return instance of CLOSURE matcher.
*
* @param mixed $closure
*
* @return \Mockery\Matcher\Closure
*/
public static function on($closure)
{
return new \Mockery\Matcher\Closure($closure);
}
/**
* Return instance of MUSTBE matcher.
*
* @param mixed $expected
*
* @return \Mockery\Matcher\MustBe
*/
public static function mustBe($expected)
{
return new \Mockery\Matcher\MustBe($expected);
}
/**
* Return instance of NOT matcher.
*
* @param mixed $expected
*
* @return \Mockery\Matcher\Not
*/
public static function not($expected)
{
return new \Mockery\Matcher\Not($expected);
}
/**
* Return instance of ANYOF matcher.
*
* @param array ...$args
*
* @return \Mockery\Matcher\AnyOf
*/
public static function anyOf(...$args)
{
return new \Mockery\Matcher\AnyOf($args);
}
/**
* Return instance of NOTANYOF matcher.
*
* @param array ...$args
*
* @return \Mockery\Matcher\NotAnyOf
*/
public static function notAnyOf(...$args)
{
return new \Mockery\Matcher\NotAnyOf($args);
}
/**
* Return instance of PATTERN matcher.
*
* @param mixed $expected
*
* @return \Mockery\Matcher\Pattern
*/
public static function pattern($expected)
{
return new \Mockery\Matcher\Pattern($expected);
}
/**
* Lazy loader and Getter for the global
* configuration container.
*
* @return \Mockery\Configuration
*/
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) . ')';
}
/**
* Gets the string representation
* of any passed argument.
*
* @param mixed $argument
* @param int $depth
*
* @return mixed
*/
private static function formatArgument($argument, $depth = 0)
{
if ($argument instanceof MatcherAbstract) {
return (string) $argument;
}
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 = '[...]';
} else {
$sample = array();
foreach ($argument as $key => $value) {
$key = is_int($key) ? $key : "'$key'";
$value = self::formatArgument($value, $depth + 1);
$sample[] = "$key => $value";
}
$argument = "[" . implode(", ", $sample) . "]";
}
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';
}
return "'" . (string) $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 $object
* @param int $nesting
*
* @return array
*/
private static function objectToArray($object, $nesting = 3)
{
if ($nesting == 0) {
return array('...');
}
$defaultFormatter = function ($object, $nesting) {
return array('properties' => self::extractInstancePublicProperties($object, $nesting));
};
$class = get_class($object);
$formatter = self::getConfiguration()->getObjectFormatter($class, $defaultFormatter);
$array = array(
'class' => $class,
'identity' => '#' . md5(spl_object_hash($object))
);
$array = array_merge($array, $formatter($object, $nesting));
return $array;
}
/**
* Returns all public instance properties.
*
* @param mixed $object
* @param int $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();
try {
$cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
} catch (\Exception $exception) {
$cleanedProperties[$name] = $exception->getMessage();
}
}
}
return $cleanedProperties;
}
/**
* Utility method used for recursively generating
* an object or array representation.
*
* @param mixed $argument
* @param int $nesting
*
* @return mixed
*/
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;
}
/**
* Utility method for recursively
* gerating a representation
* of the given array.
*
* @param array $argument
* @param int $nesting
*
* @return mixed
*/
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\LegacyMockInterface $mock
* @param array ...$args
* @param callable $add
* @return \Mockery\CompositeExpectation
*/
public static function parseShouldReturnArgs(\Mockery\LegacyMockInterface $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\LegacyMockInterface $mock
* @param string $arg
* @param callable $add
* @throws Mockery\Exception
* @return \Mockery\ExpectationInterface
*/
protected static function buildDemeterChain(\Mockery\LegacyMockInterface $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);
};
$parent = get_class($mock);
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, $parent, $method, $expectations);
} else {
$demeterMockKey = $container->getKeyOfDemeterMockFor($method, $parent);
if ($demeterMockKey) {
$mock = self::getExistingDemeterMock($container, $demeterMockKey);
}
}
$parent .= '->' . $method;
$nextExp = function ($n) use ($mock) {
return $mock->shouldReceive($n);
};
}
return $expectations;
}
/**
* Gets a new demeter configured
* mock from the container.
*
* @param \Mockery\Container $container
* @param string $parent
* @param string $method
* @param Mockery\ExpectationInterface $exp
*
* @return \Mockery\Mock
*/
private static function getNewDemeterMock(
Mockery\Container $container,
$parent,
$method,
Mockery\ExpectationInterface $exp
) {
$newMockName = 'demeter_' . md5($parent) . '_' . $method;
$parRef = null;
$parRefMethod = null;
$parRefMethodRetType = null;
$parentMock = $exp->getMock();
if ($parentMock !== null) {
$parRef = new ReflectionObject($parentMock);
}
if ($parRef !== null && $parRef->hasMethod($method)) {
$parRefMethod = $parRef->getMethod($method);
$parRefMethodRetType = Reflector::getReturnType($parRefMethod, true);
if ($parRefMethodRetType !== null && $parRefMethodRetType !== 'mixed') {
$nameBuilder = new MockNameBuilder();
$nameBuilder->addPart('\\' . $newMockName);
$mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType);
$exp->andReturn($mock);
return $mock;
}
}
$mock = $container->mock($newMockName);
$exp->andReturn($mock);
return $mock;
}
/**
* Gets an specific demeter mock from
* the ones kept by the container.
*
* @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;
}
/**
* Checks if the passed array representing a demeter
* chain with the method names is empty.
*
* @param array $methodNames
*
* @return bool
*/
private static function noMoreElementsInChain(array $methodNames)
{
return empty($methodNames);
}
public static function declareClass($fqn)
{
return static::declareType($fqn, "class");
}
public static function declareInterface($fqn)
{
return static::declareType($fqn, "interface");
}
private static function declareType($fqn, $type)
{
$targetCode = "<?php ";
$shortName = $fqn;
if (strpos($fqn, "\\")) {
$parts = explode("\\", $fqn);
$shortName = trim(array_pop($parts));
$namespace = implode("\\", $parts);
$targetCode.= "namespace $namespace;\n";
}
$targetCode.= "$type $shortName {} ";
/*
* We could eval here, but it doesn't play well with the way
* PHPUnit tries to backup global state and the require definition
* loader
*/
$tmpfname = tempnam(sys_get_temp_dir(), "Mockery");
file_put_contents($tmpfname, $targetCode);
require $tmpfname;
\Mockery::registerFileForCleanUp($tmpfname);
}
/**
* Register a file to be deleted on tearDown.
*
* @param string $fileName
*/
public static function registerFileForCleanUp($fileName)
{
self::$_filesToCleanUp[] = $fileName;
}
}

View File

@@ -0,0 +1,90 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Adapter\Phpunit;
use Mockery;
/**
* Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
* for each test and are included by the assertion counter.
*/
trait MockeryPHPUnitIntegration
{
use MockeryPHPUnitIntegrationAssertPostConditions;
protected $mockeryOpen;
/**
* Performs assertions shared by all tests of a test case. This method is
* called before execution of a test ends and before the tearDown method.
*/
protected function mockeryAssertPostConditions()
{
$this->addMockeryExpectationsToAssertionCount();
$this->checkMockeryExceptions();
$this->closeMockery();
parent::assertPostConditions();
}
protected function addMockeryExpectationsToAssertionCount()
{
$this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount());
}
protected function checkMockeryExceptions()
{
if (!method_exists($this, "markAsRisky")) {
return;
}
foreach (Mockery::getContainer()->mockery_thrownExceptions() as $e) {
if (!$e->dismissed()) {
$this->markAsRisky();
}
}
}
protected function closeMockery()
{
Mockery::close();
$this->mockeryOpen = false;
}
/**
* @before
*/
protected function startMockery()
{
$this->mockeryOpen = true;
}
/**
* @after
*/
protected function purgeMockeryContainer()
{
if ($this->mockeryOpen) {
// post conditions wasn't called, so test probably failed
Mockery::close();
}
}
}

View File

@@ -0,0 +1,31 @@
<?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) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
*/
declare(strict_types=1);
namespace Mockery\Adapter\Phpunit;
trait MockeryPHPUnitIntegrationAssertPostConditions
{
protected function assertPostConditions(): void
{
$this->mockeryAssertPostConditions();
}
}

View File

@@ -0,0 +1,35 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Adapter\Phpunit;
abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
{
use MockeryPHPUnitIntegration;
use MockeryTestCaseSetUp;
protected function mockeryTestSetUp()
{
}
protected function mockeryTestTearDown()
{
}
}

View File

@@ -0,0 +1,38 @@
<?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) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
*/
declare(strict_types=1);
namespace Mockery\Adapter\Phpunit;
trait MockeryTestCaseSetUp
{
protected function setUp(): void
{
parent::setUp();
$this->mockeryTestSetUp();
}
protected function tearDown(): void
{
$this->mockeryTestTearDown();
parent::tearDown();
}
}

View File

@@ -0,0 +1,48 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Adapter\Phpunit;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
class TestListener implements PHPUnitTestListener
{
use TestListenerDefaultImplementation;
private $trait;
public function __construct()
{
$this->trait = new TestListenerTrait();
}
public function endTest(Test $test, float $time): void
{
$this->trait->endTest($test, $time);
}
public function startTestSuite(TestSuite $suite): void
{
$this->trait->startTestSuite();
}
}

View File

@@ -0,0 +1,87 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Adapter\Phpunit;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Util\Blacklist;
use PHPUnit\Runner\BaseTestRunner;
class TestListenerTrait
{
/**
* endTest is called after each test and checks if \Mockery::close() has
* been called, and will let the test fail if it hasn't.
*
* @param Test $test
* @param float $time
*/
public function endTest(Test $test, $time)
{
if (!$test instanceof TestCase) {
// We need the getTestResultObject and getStatus methods which are
// not part of the interface.
return;
}
if ($test->getStatus() !== BaseTestRunner::STATUS_PASSED) {
// If the test didn't pass there is no guarantee that
// verifyMockObjects and assertPostConditions have been called.
// And even if it did, the point here is to prevent false
// negatives, not to make failing tests fail for more reasons.
return;
}
try {
// The self() call is used as a sentinel. Anything that throws if
// the container is closed already will do.
\Mockery::self();
} catch (\LogicException $_) {
return;
}
$e = new ExpectationFailedException(
\sprintf(
"Mockery's expectations have not been verified. Make sure that \Mockery::close() is called at the end of the test. Consider using %s\MockeryPHPUnitIntegration or extending %s\MockeryTestCase.",
__NAMESPACE__,
__NAMESPACE__
)
);
/** @var \PHPUnit\Framework\TestResult $result */
$result = $test->getTestResultObject();
if ($result !== null) {
$result->addFailure($test, $e, $time);
}
}
public function startTestSuite()
{
if (method_exists(Blacklist::class, 'addDirectory')) {
(new BlackList())->getBlacklistedDirectories();
Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName()));
} else {
Blacklist::$blacklistedClassNames[\Mockery::class] = 1;
}
}
}

View File

@@ -0,0 +1,42 @@
<?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) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
use Mockery\Matcher\Closure;
/**
* @internal
*/
class ClosureWrapper
{
private $closure;
public function __construct(\Closure $closure)
{
$this->closure = $closure;
}
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
}
}

View File

@@ -0,0 +1,154 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class CompositeExpectation implements ExpectationInterface
{
/**
* Stores an array of all expectations for this composite
*
* @var array
*/
protected $_expectations = array();
/**
* Add an expectation to the composite
*
* @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation
* @return void
*/
public function add($expectation)
{
$this->_expectations[] = $expectation;
}
/**
* @param mixed ...$args
*/
public function andReturn(...$args)
{
return $this->__call(__FUNCTION__, $args);
}
/**
* Set a return value, or sequential queue of return values
*
* @param mixed ...$args
* @return self
*/
public function andReturns(...$args)
{
return call_user_func_array([$this, 'andReturn'], $args);
}
/**
* Intercept any expectation calls and direct against all expectations
*
* @param string $method
* @param array $args
* @return self
*/
public function __call($method, array $args)
{
foreach ($this->_expectations as $expectation) {
call_user_func_array(array($expectation, $method), $args);
}
return $this;
}
/**
* Return order number of the first expectation
*
* @return int
*/
public function getOrderNumber()
{
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getOrderNumber();
}
/**
* Return the parent mock of the first expectation
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public function getMock()
{
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock();
}
/**
* Mockery API alias to getMock
*
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
*/
public function mock()
{
return $this->getMock();
}
/**
* Starts a new expectation addition on the first mock which is the primary
* target outside of a demeter chain
*
* @param mixed ...$args
* @return \Mockery\Expectation
*/
public function shouldReceive(...$args)
{
reset($this->_expectations);
$first = current($this->_expectations);
return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args);
}
/**
* Starts a new expectation addition on the first mock which is the primary
* target outside of a demeter chain
*
* @param mixed ...$args
* @return \Mockery\Expectation
*/
public function shouldNotReceive(...$args)
{
reset($this->_expectations);
$first = current($this->_expectations);
return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args);
}
/**
* Return the string summary of this composite expectation
*
* @return string
*/
public function __toString()
{
$return = '[';
$parts = array();
foreach ($this->_expectations as $exp) {
$parts[] = (string) $exp;
}
$return .= implode(', ', $parts) . ']';
return $return;
}
}

View File

@@ -0,0 +1,283 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class Configuration
{
/**
* Boolean assertion of whether we can mock methods which do not actually
* exist for the given class or object (ignored for unreal mocks)
*
* @var bool
*/
protected $_allowMockingNonExistentMethod = true;
/**
* Boolean assertion of whether we ignore unnecessary mocking of methods,
* i.e. when method expectations are made, set using a zeroOrMoreTimes()
* constraint, and then never called. Essentially such expectations are
* not required and are just taking up test space.
*
* @var bool
*/
protected $_allowMockingMethodsUnnecessarily = true;
/**
* @var QuickDefinitionsConfiguration
*/
protected $_quickDefinitionsConfiguration;
/**
* Parameter map for use with PHP internal classes.
*
* @var array
*/
protected $_internalClassParamMap = array();
protected $_constantsMap = array();
/**
* Boolean assertion is reflection caching enabled or not. It should be
* always enabled, except when using PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*/
protected $_reflectionCacheEnabled = true;
public function __construct()
{
$this->_quickDefinitionsConfiguration = new QuickDefinitionsConfiguration();
}
/**
* Custom object formatters
*
* @var array
*/
protected $_objectFormatters = array();
/**
* Default argument matchers
*
* @var array
*/
protected $_defaultMatchers = array();
/**
* Set boolean to allow/prevent mocking of non-existent methods
*
* @param bool $flag
*/
public function allowMockingNonExistentMethods($flag = true)
{
$this->_allowMockingNonExistentMethod = (bool) $flag;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*/
public function mockingNonExistentMethodsAllowed()
{
return $this->_allowMockingNonExistentMethod;
}
/**
* Set boolean to allow/prevent unnecessary mocking of methods
*
* @param bool $flag
*
* @deprecated since 1.4.0
*/
public function allowMockingMethodsUnnecessarily($flag = true)
{
@trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED);
$this->_allowMockingMethodsUnnecessarily = (bool) $flag;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*
* @deprecated since 1.4.0
*/
public function mockingMethodsUnnecessarilyAllowed()
{
@trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED);
return $this->_allowMockingMethodsUnnecessarily;
}
/**
* Set a parameter map (array of param signature strings) for the method
* of an internal PHP class.
*
* @param string $class
* @param string $method
* @param array $map
*/
public function setInternalClassMethodParamMap($class, $method, array $map)
{
if (\PHP_MAJOR_VERSION > 7) {
throw new \LogicException('Internal class parameter overriding is not available in PHP 8. Incompatible signatures have been reclassified as fatal errors.');
}
if (!isset($this->_internalClassParamMap[strtolower($class)])) {
$this->_internalClassParamMap[strtolower($class)] = array();
}
$this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map;
}
/**
* Remove all overridden parameter maps from internal PHP classes.
*/
public function resetInternalClassMethodParamMaps()
{
$this->_internalClassParamMap = array();
}
/**
* Get the parameter map of an internal PHP class method
*
* @return array|null
*/
public function getInternalClassMethodParamMap($class, $method)
{
if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) {
return $this->_internalClassParamMap[strtolower($class)][strtolower($method)];
}
}
public function getInternalClassMethodParamMaps()
{
return $this->_internalClassParamMap;
}
public function setConstantsMap(array $map)
{
$this->_constantsMap = $map;
}
public function getConstantsMap()
{
return $this->_constantsMap;
}
/**
* Returns the quick definitions configuration
*/
public function getQuickDefinitions(): QuickDefinitionsConfiguration
{
return $this->_quickDefinitionsConfiguration;
}
/**
* Disable reflection caching
*
* It should be always enabled, except when using
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*/
public function disableReflectionCache()
{
$this->_reflectionCacheEnabled = false;
}
/**
* Enable reflection caching
*
* It should be always enabled, except when using
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*/
public function enableReflectionCache()
{
$this->_reflectionCacheEnabled = true;
}
/**
* Is reflection cache enabled?
*/
public function reflectionCacheEnabled()
{
return $this->_reflectionCacheEnabled;
}
public function setObjectFormatter($class, $formatterCallback)
{
$this->_objectFormatters[$class] = $formatterCallback;
}
public function getObjectFormatter($class, $defaultFormatter)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_objectFormatters[$type])) {
return $this->_objectFormatters[$type];
}
}
return $defaultFormatter;
}
/**
* @param string $class
* @param string $matcherClass
*/
public function setDefaultMatcher($class, $matcherClass)
{
if (!is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) &&
!is_a($matcherClass, \Hamcrest\Matcher::class, true) &&
!is_a($matcherClass, \Hamcrest_Matcher::class, true)
) {
throw new \InvalidArgumentException(
"Matcher class must be either Hamcrest matcher or extend \Mockery\Matcher\MatcherAbstract, " .
"'$matcherClass' given."
);
}
$this->_defaultMatchers[$class] = $matcherClass;
}
public function getDefaultMatcher($class)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_defaultMatchers[$type])) {
return $this->_defaultMatchers[$type];
}
}
return null;
}
}

View File

@@ -0,0 +1,535 @@
<?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 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
*/
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.
*
* @param array ...$args
*
* @return Mock
* @throws Exception\RuntimeException
*/
public function mock(...$args)
{
$expectationClosure = null;
$quickdefs = array();
$constructorArgs = null;
$blocks = array();
$class = null;
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());
$builder->setConstantsMap(\Mockery::getConfiguration()->getConstantsMap());
while (count($args) > 0) {
$arg = array_shift($args);
// check for multiple interfaces
if (is_string($arg)) {
foreach (explode('|', $arg) as $type) {
if ($arg === 'null') {
// skip PHP 8 'null's
} elseif (strpos($type, ',') && !strpos($type, ']')) {
$interfaces = explode(',', str_replace(' ', '', $type));
$builder->addTargets($interfaces);
} elseif (substr($type, 0, 6) == 'alias:') {
$type = str_replace('alias:', '', $type);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, 0, 9) == 'overload:') {
$type = str_replace('overload:', '', $type);
$builder->setInstanceMock(true);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, strlen($type)-1, 1) == ']') {
$parts = explode('[', $type);
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 = array_filter(explode(',', strtolower(rtrim($parts[1], ']'))));
$builder->addTarget($class);
foreach ($partialMethods as $partialMethod) {
if ($partialMethod[0] === '!') {
$builder->addBlackListedMethod(substr($partialMethod, 1));
continue;
}
$builder->addWhiteListedMethod($partialMethod);
}
} elseif (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) {
$builder->addTarget($type);
} elseif (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() && (!class_exists($type, true) && !interface_exists($type, true))) {
throw new \Mockery\Exception("Mockery can't find '$type' so can't mock it");
} else {
if (!$this->isValidClassName($type)) {
throw new \Mockery\Exception('Class name contains invalid characters');
}
$builder->addTarget($type);
}
break; // unions are "sum" types and not "intersections", and so we must only process the first part
}
} elseif (is_object($arg)) {
$builder->addTarget($arg);
} elseif (is_array($arg)) {
if (!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 = $arg;
} else {
$constructorArgs = $arg;
}
} else {
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
} else {
$builder->setMockOriginalDestructor(true);
}
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\LegacyMockInterface")) {
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(), $config->isInstanceMock());
if (!empty($quickdefs)) {
if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickdefs)->atLeast()->once();
} else {
$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;
}
/**
* @param string $method
* @param string $parent
* @return string|null
*/
public function getKeyOfDemeterMockFor($method, $parent)
{
$keys = array_keys($this->_mocks);
$match = preg_grep("/__demeter_" . md5($parent) . "_{$method}$/", $keys);
if (count($match) == 1) {
$res = array_values($match);
if (count($res) > 0) {
return $res[0];
}
}
return null;
}
/**
* @return array
*/
public function getMocks()
{
return $this->_mocks;
}
/**
* Tear down tasks for this container
*
* @throws \Exception
* @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();
}
}
/**
* Retrieves all exceptions thrown by mocks
*
* @return array
*/
public function mockery_thrownExceptions()
{
$e = [];
foreach ($this->_mocks as $mock) {
$e = array_merge($e, $mock->mockery_thrownExceptions());
}
return $e;
}
/**
* 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\LegacyMockInterface $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 $mock
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
*/
public function rememberMock(\Mockery\LegacyMockInterface $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)
{
if ($constructorArgs !== null) {
$r = new \ReflectionClass($mockName);
return $r->newInstanceArgs($constructorArgs);
}
try {
$instantiator = new Instantiator();
$instance = $instantiator->instantiate($mockName);
} catch (\Exception $ex) {
$internalMockName = $mockName . '_Internal';
if (!class_exists($internalMockName)) {
eval("class $internalMockName extends $mockName {" .
'public function __construct() {}' .
'}');
}
$instance = new $internalMockName();
}
return $instance;
}
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;
}
/**
* see http://php.net/manual/en/language.oop5.basic.php
* @param string $className
* @return bool
*/
public function isValidClassName($className)
{
$pos = strpos($className, '\\');
if ($pos === 0) {
$className = substr($className, 1); // remove the first backslash
}
// all the namespaces and class name should match the regex
$invalidNames = array_filter(explode('\\', $className), function ($name) {
return !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
});
return empty($invalidNames);
}
}

View File

@@ -0,0 +1,62 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\CountValidator;
use Mockery;
class AtLeast extends CountValidatorAbstract
{
/**
* Checks if the validator can accept an additional nth call
*
* @param int $n
* @return bool
*/
public function isEligible($n)
{
return true;
}
/**
* Validate the call count against this validator
*
* @param int $n
* @return bool
*/
public function validate($n)
{
if ($this->_limit > $n) {
$exception = new Mockery\Exception\InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL
. ' at least ' . $this->_limit . ' times but called ' . $n
. ' times.'
);
$exception->setMock($this->_expectation->getMock())
->setMethodName((string) $this->_expectation)
->setExpectedCountComparative('>=')
->setExpectedCount($this->_limit)
->setActualCount($n);
throw $exception;
}
}
}

View File

@@ -0,0 +1,51 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\CountValidator;
use Mockery;
class AtMost extends CountValidatorAbstract
{
/**
* Validate the call count against this validator
*
* @param int $n
* @return bool
*/
public function validate($n)
{
if ($this->_limit < $n) {
$exception = new Mockery\Exception\InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL
. ' at most ' . $this->_limit . ' times but called ' . $n
. ' times.'
);
$exception->setMock($this->_expectation->getMock())
->setMethodName((string) $this->_expectation)
->setExpectedCountComparative('<=')
->setExpectedCount($this->_limit)
->setActualCount($n);
throw $exception;
}
}
}

View File

@@ -0,0 +1,69 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\CountValidator;
abstract class CountValidatorAbstract
{
/**
* Expectation for which this validator is assigned
*
* @var \Mockery\Expectation
*/
protected $_expectation = null;
/**
* Call count limit
*
* @var int
*/
protected $_limit = null;
/**
* Set Expectation object and upper call limit
*
* @param \Mockery\Expectation $expectation
* @param int $limit
*/
public function __construct(\Mockery\Expectation $expectation, $limit)
{
$this->_expectation = $expectation;
$this->_limit = $limit;
}
/**
* Checks if the validator can accept an additional nth call
*
* @param int $n
* @return bool
*/
public function isEligible($n)
{
return ($n < $this->_limit);
}
/**
* Validate the call count against this validator
*
* @param int $n
* @return bool
*/
abstract public function validate($n);
}

View File

@@ -0,0 +1,54 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\CountValidator;
use Mockery;
class Exact extends CountValidatorAbstract
{
/**
* Validate the call count against this validator
*
* @param int $n
* @return bool
*/
public function validate($n)
{
if ($this->_limit !== $n) {
$because = $this->_expectation->getExceptionMessage();
$exception = new Mockery\Exception\InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL
. ' exactly ' . $this->_limit . ' times but called ' . $n
. ' times.'
. ($because ? ' Because ' . $this->_expectation->getExceptionMessage() : '')
);
$exception->setMock($this->_expectation->getMock())
->setMethodName((string) $this->_expectation)
->setExpectedCountComparative('=')
->setExpectedCount($this->_limit)
->setActualCount($n);
throw $exception;
}
}
}

View File

@@ -0,0 +1,25 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\CountValidator;
class Exception extends \OutOfBoundsException
{
}

View File

@@ -0,0 +1,25 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class Exception extends \UnexpectedValueException
{
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Mockery\Exception;
class BadMethodCallException extends \BadMethodCallException
{
private $dismissed = false;
public function dismiss()
{
$this->dismissed = true;
// we sometimes stack them
if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) {
$this->getPrevious()->dismiss();
}
}
public function dismissed()
{
return $this->dismissed;
}
}

View File

@@ -0,0 +1,25 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Exception;
class InvalidArgumentException extends \InvalidArgumentException
{
}

View File

@@ -0,0 +1,102 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Exception;
use Mockery;
use Mockery\Exception\RuntimeException;
class InvalidCountException extends Mockery\CountValidator\Exception
{
protected $method = null;
protected $expected = 0;
protected $expectedComparative = '<=';
protected $actual = null;
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
{
$this->mockObject = $mock;
return $this;
}
public function setMethodName($name)
{
$this->method = $name;
return $this;
}
public function setActualCount($count)
{
$this->actual = $count;
return $this;
}
public function setExpectedCount($count)
{
$this->expected = $count;
return $this;
}
public function setExpectedCountComparative($comp)
{
if (!in_array($comp, array('=', '>', '<', '>=', '<='))) {
throw new RuntimeException(
'Illegal comparative for expected call counts set: ' . $comp
);
}
$this->expectedComparative = $comp;
return $this;
}
public function getMock()
{
return $this->mockObject;
}
public function getMethodName()
{
return $this->method;
}
public function getActualCount()
{
return $this->actual;
}
public function getExpectedCount()
{
return $this->expected;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
}
public function getExpectedCountComparative()
{
return $this->expectedComparative;
}
}

View File

@@ -0,0 +1,83 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Exception;
use Mockery;
class InvalidOrderException extends Mockery\Exception
{
protected $method = null;
protected $expected = 0;
protected $actual = null;
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
{
$this->mockObject = $mock;
return $this;
}
public function setMethodName($name)
{
$this->method = $name;
return $this;
}
public function setActualOrder($count)
{
$this->actual = $count;
return $this;
}
public function setExpectedOrder($count)
{
$this->expected = $count;
return $this;
}
public function getMock()
{
return $this->mockObject;
}
public function getMethodName()
{
return $this->method;
}
public function getActualOrder()
{
return $this->actual;
}
public function getExpectedOrder()
{
return $this->expected;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
}
}

View File

@@ -0,0 +1,70 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Exception;
use Mockery;
class NoMatchingExpectationException extends Mockery\Exception
{
protected $method = null;
protected $actual = array();
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
{
$this->mockObject = $mock;
return $this;
}
public function setMethodName($name)
{
$this->method = $name;
return $this;
}
public function setActualArguments($count)
{
$this->actual = $count;
return $this;
}
public function getMock()
{
return $this->mockObject;
}
public function getMethodName()
{
return $this->method;
}
public function getActualArguments()
{
return $this->actual;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
}
}

View File

@@ -0,0 +1,25 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Exception;
class RuntimeException extends \Exception
{
}

View File

@@ -0,0 +1,940 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
use Closure;
use Mockery\Matcher\NoArgs;
use Mockery\Matcher\AnyArgs;
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\ArgumentListMatcher;
use Mockery\Matcher\MultiArgumentClosure;
class Expectation implements ExpectationInterface
{
/**
* Mock object to which this expectation belongs
*
* @var \Mockery\LegacyMockInterface
*/
protected $_mock = null;
/**
* Method name
*
* @var string
*/
protected $_name = null;
/**
* Exception message
*
* @var string|null
*/
protected $_because = null;
/**
* Arguments expected by this expectation
*
* @var array
*/
protected $_expectedArgs = array();
/**
* Count validator store
*
* @var array
*/
protected $_countValidators = array();
/**
* The count validator class to use
*
* @var string
*/
protected $_countValidatorClass = 'Mockery\CountValidator\Exact';
/**
* Actual count of calls to this expectation
*
* @var int
*/
protected $_actualCount = 0;
/**
* Value to return from this expectation
*
* @var mixed
*/
protected $_returnValue = null;
/**
* Array of return values as a queue for multiple return sequence
*
* @var array
*/
protected $_returnQueue = array();
/**
* Array of closures executed with given arguments to generate a result
* to be returned
*
* @var array
*/
protected $_closureQueue = array();
/**
* Array of values to be set when this expectation matches
*
* @var array
*/
protected $_setQueue = array();
/**
* Integer representing the call order of this expectation
*
* @var int
*/
protected $_orderNumber = null;
/**
* Integer representing the call order of this expectation on a global basis
*
* @var int
*/
protected $_globalOrderNumber = null;
/**
* Flag indicating that an exception is expected to be throw (not returned)
*
* @var bool
*/
protected $_throw = false;
/**
* Flag indicating whether the order of calling is determined locally or
* globally
*
* @var bool
*/
protected $_globally = false;
/**
* Flag indicating if the return value should be obtained from the original
* class method instead of returning predefined values from the return queue
*
* @var bool
*/
protected $_passthru = false;
/**
* Constructor
*
* @param \Mockery\LegacyMockInterface $mock
* @param string $name
*/
public function __construct(\Mockery\LegacyMockInterface $mock, $name)
{
$this->_mock = $mock;
$this->_name = $name;
$this->withAnyArgs();
}
/**
* Return a string with the method name and arguments formatted
*
* @param string $name Name of the expected method
* @param array $args List of arguments to the method
* @return string
*/
public function __toString()
{
return \Mockery::formatArgs($this->_name, $this->_expectedArgs);
}
/**
* Verify the current call, i.e. that the given arguments match those
* of this expectation
*
* @param array $args
* @return mixed
*/
public function verifyCall(array $args)
{
$this->validateOrder();
$this->_actualCount++;
if (true === $this->_passthru) {
return $this->_mock->mockery_callSubjectMethod($this->_name, $args);
}
$return = $this->_getReturnValue($args);
$this->throwAsNecessary($return);
$this->_setValues();
return $return;
}
/**
* Throws an exception if the expectation has been configured to do so
*
* @throws \Throwable
* @return void
*/
private function throwAsNecessary($return)
{
if (!$this->_throw) {
return;
}
if ($return instanceof \Throwable) {
throw $return;
}
return;
}
/**
* Sets public properties with queued values to the mock object
*
* @param array $args
* @return mixed
*/
protected function _setValues()
{
$mockClass = get_class($this->_mock);
$container = $this->_mock->mockery_getContainer();
/** @var Mock[] $mocks */
$mocks = $container->getMocks();
foreach ($this->_setQueue as $name => &$values) {
if (count($values) > 0) {
$value = array_shift($values);
$this->_mock->{$name} = $value;
foreach ($mocks as $mock) {
if (is_a($mock, $mockClass) && $mock->mockery_isInstance()) {
$mock->{$name} = $value;
}
}
}
}
}
/**
* Fetch the return value for the matching args
*
* @param array $args
* @return mixed
*/
protected function _getReturnValue(array $args)
{
if (count($this->_closureQueue) > 1) {
return call_user_func_array(array_shift($this->_closureQueue), $args);
} elseif (count($this->_closureQueue) > 0) {
return call_user_func_array(current($this->_closureQueue), $args);
} elseif (count($this->_returnQueue) > 1) {
return array_shift($this->_returnQueue);
} elseif (count($this->_returnQueue) > 0) {
return current($this->_returnQueue);
}
return $this->_mock->mockery_returnValueForMethod($this->_name);
}
/**
* Checks if this expectation is eligible for additional calls
*
* @return bool
*/
public function isEligible()
{
foreach ($this->_countValidators as $validator) {
if (!$validator->isEligible($this->_actualCount)) {
return false;
}
}
return true;
}
/**
* Check if there is a constraint on call count
*
* @return bool
*/
public function isCallCountConstrained()
{
return (count($this->_countValidators) > 0);
}
/**
* Verify call order
*
* @return void
*/
public function validateOrder()
{
if ($this->_orderNumber) {
$this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock);
}
if ($this->_globalOrderNumber) {
$this->_mock->mockery_getContainer()
->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock);
}
}
/**
* Verify this expectation
*
* @return void
*/
public function verify()
{
foreach ($this->_countValidators as $validator) {
$validator->validate($this->_actualCount);
}
}
/**
* Check if the registered expectation is an ArgumentListMatcher
* @return bool
*/
private function isArgumentListMatcher()
{
return (count($this->_expectedArgs) === 1 && ($this->_expectedArgs[0] instanceof ArgumentListMatcher));
}
private function isAndAnyOtherArgumentsMatcher($expectedArg)
{
return $expectedArg instanceof AndAnyOtherArgs;
}
/**
* Check if passed arguments match an argument expectation
*
* @param array $args
* @return bool
*/
public function matchArgs(array $args)
{
if ($this->isArgumentListMatcher()) {
return $this->_matchArg($this->_expectedArgs[0], $args);
}
$argCount = count($args);
if ($argCount !== count((array) $this->_expectedArgs)) {
$lastExpectedArgument = end($this->_expectedArgs);
reset($this->_expectedArgs);
if ($this->isAndAnyOtherArgumentsMatcher($lastExpectedArgument)) {
$args = array_slice($args, 0, array_search($lastExpectedArgument, $this->_expectedArgs, true));
return $this->_matchArgs($args);
}
return false;
}
return $this->_matchArgs($args);
}
/**
* Check if the passed arguments match the expectations, one by one.
*
* @param array $args
* @return bool
*/
protected function _matchArgs($args)
{
$argCount = count($args);
for ($i=0; $i<$argCount; $i++) {
$param =& $args[$i];
if (!$this->_matchArg($this->_expectedArgs[$i], $param)) {
return false;
}
}
return true;
}
/**
* Check if passed argument matches an argument expectation
*
* @param mixed $expected
* @param mixed $actual
* @return bool
*/
protected function _matchArg($expected, &$actual)
{
if ($expected === $actual) {
return true;
}
if (!is_object($expected) && !is_object($actual) && $expected == $actual) {
return true;
}
if (is_string($expected) && is_object($actual)) {
$result = $actual instanceof $expected;
if ($result) {
return true;
}
}
if (is_object($expected)) {
$matcher = \Mockery::getConfiguration()->getDefaultMatcher(get_class($expected));
if ($matcher !== null) {
$expected = new $matcher($expected);
}
}
if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
return $expected->match($actual);
}
if ($expected instanceof \Hamcrest\Matcher || $expected instanceof \Hamcrest_Matcher) {
return $expected->matches($actual);
}
return false;
}
/**
* Expected argument setter for the expectation
*
* @param mixed ...$args
*
* @return self
*/
public function with(...$args)
{
return $this->withArgs($args);
}
/**
* Expected arguments for the expectation passed as an array
*
* @param array $arguments
* @return self
*/
private function withArgsInArray(array $arguments)
{
if (empty($arguments)) {
return $this->withNoArgs();
}
$this->_expectedArgs = $arguments;
return $this;
}
/**
* Expected arguments have to be matched by the given closure.
*
* @param Closure $closure
* @return self
*/
private function withArgsMatchedByClosure(Closure $closure)
{
$this->_expectedArgs = [new MultiArgumentClosure($closure)];
return $this;
}
/**
* Expected arguments for the expectation passed as an array or a closure that matches each passed argument on
* each function call.
*
* @param array|Closure $argsOrClosure
* @return self
*/
public function withArgs($argsOrClosure)
{
if (is_array($argsOrClosure)) {
$this->withArgsInArray($argsOrClosure);
} elseif ($argsOrClosure instanceof Closure) {
$this->withArgsMatchedByClosure($argsOrClosure);
} else {
throw new \InvalidArgumentException(sprintf('Call to %s with an invalid argument (%s), only array and ' .
'closure are allowed', __METHOD__, $argsOrClosure));
}
return $this;
}
/**
* Set with() as no arguments expected
*
* @return self
*/
public function withNoArgs()
{
$this->_expectedArgs = [new NoArgs()];
return $this;
}
/**
* Set expectation that any arguments are acceptable
*
* @return self
*/
public function withAnyArgs()
{
$this->_expectedArgs = [new AnyArgs()];
return $this;
}
/**
* Expected arguments should partially match the real arguments
*
* @param mixed ...$expectedArgs
* @return self
*/
public function withSomeOfArgs(...$expectedArgs)
{
return $this->withArgs(function (...$args) use ($expectedArgs) {
foreach ($expectedArgs as $expectedArg) {
if (!in_array($expectedArg, $args, true)) {
return false;
}
}
return true;
});
}
/**
* Set a return value, or sequential queue of return values
*
* @param mixed ...$args
* @return self
*/
public function andReturn(...$args)
{
$this->_returnQueue = $args;
return $this;
}
/**
* Set a return value, or sequential queue of return values
*
* @param mixed ...$args
* @return self
*/
public function andReturns(...$args)
{
return call_user_func_array([$this, 'andReturn'], $args);
}
/**
* Return this mock, like a fluent interface
*
* @return self
*/
public function andReturnSelf()
{
return $this->andReturn($this->_mock);
}
/**
* Set a sequential queue of return values with an array
*
* @param array $values
* @return self
*/
public function andReturnValues(array $values)
{
call_user_func_array(array($this, 'andReturn'), $values);
return $this;
}
/**
* Set a closure or sequence of closures with which to generate return
* values. The arguments passed to the expected method are passed to the
* closures as parameters.
*
* @param callable ...$args
* @return self
*/
public function andReturnUsing(...$args)
{
$this->_closureQueue = $args;
return $this;
}
/**
* Sets up a closure to return the nth argument from the expected method call
*
* @param int $index
* @return self
*/
public function andReturnArg($index)
{
if (!is_int($index) || $index < 0) {
throw new \InvalidArgumentException("Invalid argument index supplied. Index must be a non-negative integer.");
}
$closure = function (...$args) use ($index) {
if (array_key_exists($index, $args)) {
return $args[$index];
}
throw new \OutOfBoundsException("Cannot return an argument value. No argument exists for the index $index");
};
$this->_closureQueue = [$closure];
return $this;
}
/**
* Return a self-returning black hole object.
*
* @return self
*/
public function andReturnUndefined()
{
$this->andReturn(new \Mockery\Undefined());
return $this;
}
/**
* Return null. This is merely a language construct for Mock describing.
*
* @return self
*/
public function andReturnNull()
{
return $this->andReturn(null);
}
public function andReturnFalse()
{
return $this->andReturn(false);
}
public function andReturnTrue()
{
return $this->andReturn(true);
}
/**
* Set Exception class and arguments to that class to be thrown
*
* @param string|\Exception $exception
* @param string $message
* @param int $code
* @param \Exception $previous
* @return self
*/
public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
{
$this->_throw = true;
if (is_object($exception)) {
$this->andReturn($exception);
} else {
$this->andReturn(new $exception($message, $code, $previous));
}
return $this;
}
public function andThrows($exception, $message = '', $code = 0, \Exception $previous = null)
{
return $this->andThrow($exception, $message, $code, $previous);
}
/**
* Set Exception classes to be thrown
*
* @param array $exceptions
* @return self
*/
public function andThrowExceptions(array $exceptions)
{
$this->_throw = true;
foreach ($exceptions as $exception) {
if (!is_object($exception)) {
throw new Exception('You must pass an array of exception objects to andThrowExceptions');
}
}
return $this->andReturnValues($exceptions);
}
/**
* Register values to be set to a public property each time this expectation occurs
*
* @param string $name
* @param array ...$values
* @return self
*/
public function andSet($name, ...$values)
{
$this->_setQueue[$name] = $values;
return $this;
}
/**
* Sets up a closure that will yield each of the provided args
*
* @param mixed ...$args
* @return self
*/
public function andYield(...$args)
{
$this->_closureQueue = [
static function () use ($args) {
foreach ($args as $arg) {
yield $arg;
}
},
];
return $this;
}
/**
* Alias to andSet(). Allows the natural English construct
* - set('foo', 'bar')->andReturn('bar')
*
* @param string $name
* @param mixed $value
* @return self
*/
public function set($name, $value)
{
return call_user_func_array(array($this, 'andSet'), func_get_args());
}
/**
* Indicates this expectation should occur zero or more times
*
* @return self
*/
public function zeroOrMoreTimes()
{
$this->atLeast()->never();
}
/**
* Indicates the number of times this expectation should occur
*
* @param int $limit
* @throws \InvalidArgumentException
* @return self
*/
public function times($limit = null)
{
if (is_null($limit)) {
return $this;
}
if (!is_int($limit)) {
throw new \InvalidArgumentException('The passed Times limit should be an integer value');
}
$this->_countValidators[$this->_countValidatorClass] = new $this->_countValidatorClass($this, $limit);
if ('Mockery\CountValidator\Exact' !== $this->_countValidatorClass) {
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
unset($this->_countValidators[$this->_countValidatorClass]);
}
return $this;
}
/**
* Indicates that this expectation is never expected to be called
*
* @return self
*/
public function never()
{
return $this->times(0);
}
/**
* Indicates that this expectation is expected exactly once
*
* @return self
*/
public function once()
{
return $this->times(1);
}
/**
* Indicates that this expectation is expected exactly twice
*
* @return self
*/
public function twice()
{
return $this->times(2);
}
/**
* Sets next count validator to the AtLeast instance
*
* @return self
*/
public function atLeast()
{
$this->_countValidatorClass = 'Mockery\CountValidator\AtLeast';
return $this;
}
/**
* Sets next count validator to the AtMost instance
*
* @return self
*/
public function atMost()
{
$this->_countValidatorClass = 'Mockery\CountValidator\AtMost';
return $this;
}
/**
* Shorthand for setting minimum and maximum constraints on call counts
*
* @param int $minimum
* @param int $maximum
*/
public function between($minimum, $maximum)
{
return $this->atLeast()->times($minimum)->atMost()->times($maximum);
}
/**
* Set the exception message
*
* @param string $message
* @return $this
*/
public function because($message)
{
$this->_because = $message;
return $this;
}
/**
* Indicates that this expectation must be called in a specific given order
*
* @param string $group Name of the ordered group
* @return self
*/
public function ordered($group = null)
{
if ($this->_globally) {
$this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer());
} else {
$this->_orderNumber = $this->_defineOrdered($group, $this->_mock);
}
$this->_globally = false;
return $this;
}
/**
* Indicates call order should apply globally
*
* @return self
*/
public function globally()
{
$this->_globally = true;
return $this;
}
/**
* Setup the ordering tracking on the mock or mock container
*
* @param string $group
* @param object $ordering
* @return int
*/
protected function _defineOrdered($group, $ordering)
{
$groups = $ordering->mockery_getGroups();
if (is_null($group)) {
$result = $ordering->mockery_allocateOrder();
} elseif (isset($groups[$group])) {
$result = $groups[$group];
} else {
$result = $ordering->mockery_allocateOrder();
$ordering->mockery_setGroup($group, $result);
}
return $result;
}
/**
* Return order number
*
* @return int
*/
public function getOrderNumber()
{
return $this->_orderNumber;
}
/**
* Mark this expectation as being a default
*
* @return self
*/
public function byDefault()
{
$director = $this->_mock->mockery_getExpectationsFor($this->_name);
if (!empty($director)) {
$director->makeExpectationDefault($this);
}
return $this;
}
/**
* Return the parent mock of the expectation
*
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
*/
public function getMock()
{
return $this->_mock;
}
/**
* Flag this expectation as calling the original class method with the
* any provided arguments instead of using a return value queue.
*
* @return self
*/
public function passthru()
{
if ($this->_mock instanceof Mock) {
throw new Exception(
'Mock Objects not created from a loaded/existing class are '
. 'incapable of passing method calls through to a parent class'
);
}
$this->_passthru = true;
return $this;
}
/**
* Cloning logic
*
*/
public function __clone()
{
$newValidators = array();
$countValidators = $this->_countValidators;
foreach ($countValidators as $validator) {
$newValidators[] = clone $validator;
}
$this->_countValidators = $newValidators;
}
public function getName()
{
return $this->_name;
}
public function getExceptionMessage()
{
return $this->_because;
}
}

View File

@@ -0,0 +1,218 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class ExpectationDirector
{
/**
* Method name the director is directing
*
* @var string
*/
protected $_name = null;
/**
* Mock object the director is attached to
*
* @var \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
protected $_mock = null;
/**
* Stores an array of all expectations for this mock
*
* @var array
*/
protected $_expectations = array();
/**
* The expected order of next call
*
* @var int
*/
protected $_expectedOrder = null;
/**
* Stores an array of all default expectations for this mock
*
* @var array
*/
protected $_defaults = array();
/**
* Constructor
*
* @param string $name
* @param \Mockery\LegacyMockInterface $mock
*/
public function __construct($name, \Mockery\LegacyMockInterface $mock)
{
$this->_name = $name;
$this->_mock = $mock;
}
/**
* Add a new expectation to the director
*
* @param \Mockery\Expectation $expectation
*/
public function addExpectation(\Mockery\Expectation $expectation)
{
$this->_expectations[] = $expectation;
}
/**
* Handle a method call being directed by this instance
*
* @param array $args
* @return mixed
*/
public function call(array $args)
{
$expectation = $this->findExpectation($args);
if (is_null($expectation)) {
$exception = new \Mockery\Exception\NoMatchingExpectationException(
'No matching handler found for '
. $this->_mock->mockery_getName() . '::'
. \Mockery::formatArgs($this->_name, $args)
. '. Either the method was unexpected or its arguments matched'
. ' no expected argument list for this method'
. PHP_EOL . PHP_EOL
. \Mockery::formatObjects($args)
);
$exception->setMock($this->_mock)
->setMethodName($this->_name)
->setActualArguments($args);
throw $exception;
}
return $expectation->verifyCall($args);
}
/**
* Verify all expectations of the director
*
* @throws \Mockery\CountValidator\Exception
* @return void
*/
public function verify()
{
if (!empty($this->_expectations)) {
foreach ($this->_expectations as $exp) {
$exp->verify();
}
} else {
foreach ($this->_defaults as $exp) {
$exp->verify();
}
}
}
/**
* Attempt to locate an expectation matching the provided args
*
* @param array $args
* @return mixed
*/
public function findExpectation(array $args)
{
$expectation = null;
if (!empty($this->_expectations)) {
$expectation = $this->_findExpectationIn($this->_expectations, $args);
}
if ($expectation === null && !empty($this->_defaults)) {
$expectation = $this->_findExpectationIn($this->_defaults, $args);
}
return $expectation;
}
/**
* Make the given expectation a default for all others assuming it was
* correctly created last
*
* @param \Mockery\Expectation $expectation
*/
public function makeExpectationDefault(\Mockery\Expectation $expectation)
{
$last = end($this->_expectations);
if ($last === $expectation) {
array_pop($this->_expectations);
array_unshift($this->_defaults, $expectation);
} else {
throw new \Mockery\Exception(
'Cannot turn a previously defined expectation into a default'
);
}
}
/**
* Search current array of expectations for a match
*
* @param array $expectations
* @param array $args
* @return mixed
*/
protected function _findExpectationIn(array $expectations, array $args)
{
foreach ($expectations as $exp) {
if ($exp->isEligible() && $exp->matchArgs($args)) {
return $exp;
}
}
foreach ($expectations as $exp) {
if ($exp->matchArgs($args)) {
return $exp;
}
}
}
/**
* Return all expectations assigned to this director
*
* @return array
*/
public function getExpectations()
{
return $this->_expectations;
}
/**
* Return all expectations assigned to this director
*
* @return array
*/
public function getDefaultExpectations()
{
return $this->_defaults;
}
/**
* Return the number of expectations assigned to this director.
*
* @return int
*/
public function getExpectationCount()
{
return count($this->getExpectations()) ?: count($this->getDefaultExpectations());
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
interface ExpectationInterface
{
/**
* @return int
*/
public function getOrderNumber();
/**
* @return LegacyMockInterface|MockInterface
*/
public function getMock();
/**
* @param mixed $args
* @return self
*/
public function andReturn(...$args);
/**
* @return self
*/
public function andReturns();
}

View File

@@ -0,0 +1,38 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class ExpectsHigherOrderMessage extends HigherOrderMessage
{
public function __construct(MockInterface $mock)
{
parent::__construct($mock, "shouldReceive");
}
/**
* @return \Mockery\Expectation
*/
public function __call($method, $args)
{
$expectation = parent::__call($method, $args);
return $expectation->once();
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class CachingGenerator implements Generator
{
protected $generator;
protected $cache = array();
public function __construct(Generator $generator)
{
$this->generator = $generator;
}
public function generate(MockConfiguration $config)
{
$hash = $config->getHash();
if (isset($this->cache[$hash])) {
return $this->cache[$hash];
}
$definition = $this->generator->generate($config);
$this->cache[$hash] = $definition;
return $definition;
}
}

View File

@@ -0,0 +1,110 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class DefinedTargetClass implements TargetClassInterface
{
private $rfc;
private $name;
public function __construct(\ReflectionClass $rfc, $alias = null)
{
$this->rfc = $rfc;
$this->name = $alias === null ? $rfc->getName() : $alias;
}
public static function factory($name, $alias = null)
{
return new self(new \ReflectionClass($name), $alias);
}
public function getName()
{
return $this->name;
}
public function isAbstract()
{
return $this->rfc->isAbstract();
}
public function isFinal()
{
return $this->rfc->isFinal();
}
public function getMethods()
{
return array_map(function ($method) {
return new Method($method);
}, $this->rfc->getMethods());
}
public function getInterfaces()
{
$class = __CLASS__;
return array_map(function ($interface) use ($class) {
return new $class($interface);
}, $this->rfc->getInterfaces());
}
public function __toString()
{
return $this->getName();
}
public function getNamespaceName()
{
return $this->rfc->getNamespaceName();
}
public function inNamespace()
{
return $this->rfc->inNamespace();
}
public function getShortName()
{
return $this->rfc->getShortName();
}
public function implementsInterface($interface)
{
return $this->rfc->implementsInterface($interface);
}
public function hasInternalAncestor()
{
if ($this->rfc->isInternal()) {
return true;
}
$child = $this->rfc;
while ($parent = $child->getParentClass()) {
if ($parent->isInternal()) {
return true;
}
$child = $parent;
}
return false;
}
}

View File

@@ -0,0 +1,27 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
interface Generator
{
/** @returns MockDefinition */
public function generate(MockConfiguration $config);
}

View File

@@ -0,0 +1,57 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
use Mockery\Reflector;
class Method
{
/** @var \ReflectionMethod */
private $method;
public function __construct(\ReflectionMethod $method)
{
$this->method = $method;
}
public function __call($method, $args)
{
return call_user_func_array(array($this->method, $method), $args);
}
/**
* @return Parameter[]
*/
public function getParameters()
{
return array_map(function (\ReflectionParameter $parameter) {
return new Parameter($parameter);
}, $this->method->getParameters());
}
/**
* @return string|null
*/
public function getReturnType()
{
return Reflector::getReturnType($this->method);
}
}

View File

@@ -0,0 +1,556 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
/**
* This class describes the configuration of mocks and hides away some of the
* reflection implementation
*/
class MockConfiguration
{
/**
* A class that we'd like to mock
*/
protected $targetClass;
protected $targetClassName;
/**
* A number of interfaces we'd like to mock, keyed by name to attempt to
* keep unique
*/
protected $targetInterfaces = array();
protected $targetInterfaceNames = array();
/**
* A number of traits we'd like to mock, keyed by name to attempt to
* keep unique
*/
protected $targetTraits = array();
protected $targetTraitNames = array();
/**
* An object we'd like our mock to proxy to
*/
protected $targetObject;
/**
* The class name we'd like to use for a generated mock
*/
protected $name;
/**
* Methods that should specifically not be mocked
*
* This is currently populated with stuff we don't know how to deal with,
* should really be somewhere else
*/
protected $blackListedMethods = array();
/**
* If not empty, only these methods will be mocked
*/
protected $whiteListedMethods = array();
/**
* An instance mock is where we override the original class before it's
* autoloaded
*/
protected $instanceMock = false;
/**
* Param overrides
*/
protected $parameterOverrides = array();
/**
* Instance cache of all methods
*/
protected $allMethods;
/**
* If true, overrides original class destructor
*/
protected $mockOriginalDestructor = false;
protected $constantsMap = array();
public function __construct(
array $targets = array(),
array $blackListedMethods = array(),
array $whiteListedMethods = array(),
$name = null,
$instanceMock = false,
array $parameterOverrides = array(),
$mockOriginalDestructor = false,
array $constantsMap = array()
) {
$this->addTargets($targets);
$this->blackListedMethods = $blackListedMethods;
$this->whiteListedMethods = $whiteListedMethods;
$this->name = $name;
$this->instanceMock = $instanceMock;
$this->parameterOverrides = $parameterOverrides;
$this->mockOriginalDestructor = $mockOriginalDestructor;
$this->constantsMap = $constantsMap;
}
/**
* Attempt to create a hash of the configuration, in order to allow caching
*
* @TODO workout if this will work
*
* @return string
*/
public function getHash()
{
$vars = array(
'targetClassName' => $this->targetClassName,
'targetInterfaceNames' => $this->targetInterfaceNames,
'targetTraitNames' => $this->targetTraitNames,
'name' => $this->name,
'blackListedMethods' => $this->blackListedMethods,
'whiteListedMethod' => $this->whiteListedMethods,
'instanceMock' => $this->instanceMock,
'parameterOverrides' => $this->parameterOverrides,
'mockOriginalDestructor' => $this->mockOriginalDestructor
);
return md5(serialize($vars));
}
/**
* Gets a list of methods from the classes, interfaces and objects and
* filters them appropriately. Lot's of filtering going on, perhaps we could
* have filter classes to iterate through
*/
public function getMethodsToMock()
{
$methods = $this->getAllMethods();
foreach ($methods as $key => $method) {
if ($method->isFinal()) {
unset($methods[$key]);
}
}
/**
* Whitelist trumps everything else
*/
if (count($this->getWhiteListedMethods())) {
$whitelist = array_map('strtolower', $this->getWhiteListedMethods());
$methods = array_filter($methods, function ($method) use ($whitelist) {
return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist);
});
return $methods;
}
/**
* Remove blacklisted methods
*/
if (count($this->getBlackListedMethods())) {
$blacklist = array_map('strtolower', $this->getBlackListedMethods());
$methods = array_filter($methods, function ($method) use ($blacklist) {
return !in_array(strtolower($method->getName()), $blacklist);
});
}
/**
* Internal objects can not be instantiated with newInstanceArgs and if
* they implement Serializable, unserialize will have to be called. As
* such, we can't mock it and will need a pass to add a dummy
* implementation
*/
if ($this->getTargetClass()
&& $this->getTargetClass()->implementsInterface("Serializable")
&& $this->getTargetClass()->hasInternalAncestor()) {
$methods = array_filter($methods, function ($method) {
return $method->getName() !== "unserialize";
});
}
return array_values($methods);
}
/**
* We declare the __call method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
*/
public function requiresCallTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ("__call" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
}
}
return false;
}
/**
* We declare the __callStatic method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
*/
public function requiresCallStaticTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ("__callStatic" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
}
}
return false;
}
public function rename($className)
{
$targets = array();
if ($this->targetClassName) {
$targets[] = $this->targetClassName;
}
if ($this->targetInterfaceNames) {
$targets = array_merge($targets, $this->targetInterfaceNames);
}
if ($this->targetTraitNames) {
$targets = array_merge($targets, $this->targetTraitNames);
}
if ($this->targetObject) {
$targets[] = $this->targetObject;
}
return new self(
$targets,
$this->blackListedMethods,
$this->whiteListedMethods,
$className,
$this->instanceMock,
$this->parameterOverrides,
$this->mockOriginalDestructor,
$this->constantsMap
);
}
protected function addTarget($target)
{
if (is_object($target)) {
$this->setTargetObject($target);
$this->setTargetClassName(get_class($target));
return $this;
}
if ($target[0] !== "\\") {
$target = "\\" . $target;
}
if (class_exists($target)) {
$this->setTargetClassName($target);
return $this;
}
if (interface_exists($target)) {
$this->addTargetInterfaceName($target);
return $this;
}
if (trait_exists($target)) {
$this->addTargetTraitName($target);
return $this;
}
/**
* Default is to set as class, or interface if class already set
*
* Don't like this condition, can't remember what the default
* targetClass is for
*/
if ($this->getTargetClassName()) {
$this->addTargetInterfaceName($target);
return $this;
}
$this->setTargetClassName($target);
}
protected function addTargets($interfaces)
{
foreach ($interfaces as $interface) {
$this->addTarget($interface);
}
}
public function getTargetClassName()
{
return $this->targetClassName;
}
public function getTargetClass()
{
if ($this->targetClass) {
return $this->targetClass;
}
if (!$this->targetClassName) {
return null;
}
if (class_exists($this->targetClassName)) {
$alias = null;
if (strpos($this->targetClassName, '@') !== false) {
$alias = (new MockNameBuilder())
->addPart('anonymous_class')
->addPart(md5($this->targetClassName))
->build();
class_alias($this->targetClassName, $alias);
}
$dtc = DefinedTargetClass::factory($this->targetClassName, $alias);
if ($this->getTargetObject() == false && $dtc->isFinal()) {
throw new \Mockery\Exception(
'The class ' . $this->targetClassName . ' is marked final and its methods'
. ' cannot be replaced. Classes marked final can be passed in'
. ' to \Mockery::mock() as instantiated objects to create a'
. ' partial mock, but only if the mock is not subject to type'
. ' hinting checks.'
);
}
$this->targetClass = $dtc;
} else {
$this->targetClass = UndefinedTargetClass::factory($this->targetClassName);
}
return $this->targetClass;
}
public function getTargetTraits()
{
if (!empty($this->targetTraits)) {
return $this->targetTraits;
}
foreach ($this->targetTraitNames as $targetTrait) {
$this->targetTraits[] = DefinedTargetClass::factory($targetTrait);
}
$this->targetTraits = array_unique($this->targetTraits); // just in case
return $this->targetTraits;
}
public function getTargetInterfaces()
{
if (!empty($this->targetInterfaces)) {
return $this->targetInterfaces;
}
foreach ($this->targetInterfaceNames as $targetInterface) {
if (!interface_exists($targetInterface)) {
$this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface);
continue;
}
$dtc = DefinedTargetClass::factory($targetInterface);
$extendedInterfaces = array_keys($dtc->getInterfaces());
$extendedInterfaces[] = $targetInterface;
$traversableFound = false;
$iteratorShiftedToFront = false;
foreach ($extendedInterfaces as $interface) {
if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) {
break;
}
if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
$iteratorShiftedToFront = true;
} elseif (preg_match("/^\\\\?Iterator$/i", $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator");
$iteratorShiftedToFront = true;
} elseif (preg_match("/^\\\\?Traversable$/i", $interface)) {
$traversableFound = true;
}
}
if ($traversableFound && !$iteratorShiftedToFront) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
}
/**
* We never straight up implement Traversable
*/
if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) {
$this->targetInterfaces[] = $dtc;
}
}
$this->targetInterfaces = array_unique($this->targetInterfaces); // just in case
return $this->targetInterfaces;
}
public function getTargetObject()
{
return $this->targetObject;
}
public function getName()
{
return $this->name;
}
/**
* Generate a suitable name based on the config
*/
public function generateName()
{
$nameBuilder = new MockNameBuilder();
if ($this->getTargetObject()) {
$className = get_class($this->getTargetObject());
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
if ($this->getTargetClass()) {
$className = $this->getTargetClass()->getName();
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
foreach ($this->getTargetInterfaces() as $targetInterface) {
$nameBuilder->addPart($targetInterface->getName());
}
return $nameBuilder->build();
}
public function getShortName()
{
$parts = explode("\\", $this->getName());
return array_pop($parts);
}
public function getNamespaceName()
{
$parts = explode("\\", $this->getName());
array_pop($parts);
if (count($parts)) {
return implode("\\", $parts);
}
return "";
}
public function getBlackListedMethods()
{
return $this->blackListedMethods;
}
public function getWhiteListedMethods()
{
return $this->whiteListedMethods;
}
public function isInstanceMock()
{
return $this->instanceMock;
}
public function getParameterOverrides()
{
return $this->parameterOverrides;
}
public function isMockOriginalDestructor()
{
return $this->mockOriginalDestructor;
}
protected function setTargetClassName($targetClassName)
{
$this->targetClassName = $targetClassName;
}
protected function getAllMethods()
{
if ($this->allMethods) {
return $this->allMethods;
}
$classes = $this->getTargetInterfaces();
if ($this->getTargetClass()) {
$classes[] = $this->getTargetClass();
}
$methods = array();
foreach ($classes as $class) {
$methods = array_merge($methods, $class->getMethods());
}
foreach ($this->getTargetTraits() as $trait) {
foreach ($trait->getMethods() as $method) {
if ($method->isAbstract()) {
$methods[] = $method;
}
}
}
$names = array();
$methods = array_filter($methods, function ($method) use (&$names) {
if (in_array($method->getName(), $names)) {
return false;
}
$names[] = $method->getName();
return true;
});
return $this->allMethods = $methods;
}
/**
* If we attempt to implement Traversable, we must ensure we are also
* implementing either Iterator or IteratorAggregate, and that whichever one
* it is comes before Traversable in the list of implements.
*/
protected function addTargetInterfaceName($targetInterface)
{
$this->targetInterfaceNames[] = $targetInterface;
}
protected function addTargetTraitName($targetTraitName)
{
$this->targetTraitNames[] = $targetTraitName;
}
protected function setTargetObject($object)
{
$this->targetObject = $object;
}
public function getConstantsMap()
{
return $this->constantsMap;
}
}

View File

@@ -0,0 +1,174 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class MockConfigurationBuilder
{
protected $name;
protected $blackListedMethods = array(
'__call',
'__callStatic',
'__clone',
'__wakeup',
'__set',
'__get',
'__toString',
'__isset',
'__destruct',
'__debugInfo', ## mocking this makes it difficult to debug with xdebug
// below are reserved words in PHP
"__halt_compiler", "abstract", "and", "array", "as",
"break", "callable", "case", "catch", "class",
"clone", "const", "continue", "declare", "default",
"die", "do", "echo", "else", "elseif",
"empty", "enddeclare", "endfor", "endforeach", "endif",
"endswitch", "endwhile", "eval", "exit", "extends",
"final", "for", "foreach", "function", "global",
"goto", "if", "implements", "include", "include_once",
"instanceof", "insteadof", "interface", "isset", "list",
"namespace", "new", "or", "print", "private",
"protected", "public", "require", "require_once", "return",
"static", "switch", "throw", "trait", "try",
"unset", "use", "var", "while", "xor"
);
protected $php7SemiReservedKeywords = [
"callable", "class", "trait", "extends", "implements", "static", "abstract", "final",
"public", "protected", "private", "const", "enddeclare", "endfor", "endforeach", "endif",
"endwhile", "and", "global", "goto", "instanceof", "insteadof", "interface", "namespace", "new",
"or", "xor", "try", "use", "var", "exit", "list", "clone", "include", "include_once", "throw",
"array", "print", "echo", "require", "require_once", "return", "else", "elseif", "default",
"break", "continue", "switch", "yield", "function", "if", "endswitch", "finally", "for", "foreach",
"declare", "case", "do", "while", "as", "catch", "die", "self", "parent",
];
protected $whiteListedMethods = array();
protected $instanceMock = false;
protected $parameterOverrides = array();
protected $mockOriginalDestructor = false;
protected $targets = array();
protected $constantsMap = array();
public function __construct()
{
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
}
public function addTarget($target)
{
$this->targets[] = $target;
return $this;
}
public function addTargets($targets)
{
foreach ($targets as $target) {
$this->addTarget($target);
}
return $this;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function addBlackListedMethod($blackListedMethod)
{
$this->blackListedMethods[] = $blackListedMethod;
return $this;
}
public function addBlackListedMethods(array $blackListedMethods)
{
foreach ($blackListedMethods as $method) {
$this->addBlackListedMethod($method);
}
return $this;
}
public function setBlackListedMethods(array $blackListedMethods)
{
$this->blackListedMethods = $blackListedMethods;
return $this;
}
public function addWhiteListedMethod($whiteListedMethod)
{
$this->whiteListedMethods[] = $whiteListedMethod;
return $this;
}
public function addWhiteListedMethods(array $whiteListedMethods)
{
foreach ($whiteListedMethods as $method) {
$this->addWhiteListedMethod($method);
}
return $this;
}
public function setWhiteListedMethods(array $whiteListedMethods)
{
$this->whiteListedMethods = $whiteListedMethods;
return $this;
}
public function setInstanceMock($instanceMock)
{
$this->instanceMock = (bool) $instanceMock;
}
public function setParameterOverrides(array $overrides)
{
$this->parameterOverrides = $overrides;
}
public function setMockOriginalDestructor($mockDestructor)
{
$this->mockOriginalDestructor = $mockDestructor;
return $this;
}
public function setConstantsMap(array $map)
{
$this->constantsMap = $map;
}
public function getMockConfiguration()
{
return new MockConfiguration(
$this->targets,
$this->blackListedMethods,
$this->whiteListedMethods,
$this->name,
$this->instanceMock,
$this->parameterOverrides,
$this->mockOriginalDestructor,
$this->constantsMap
);
}
}

View File

@@ -0,0 +1,51 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class MockDefinition
{
protected $config;
protected $code;
public function __construct(MockConfiguration $config, $code)
{
if (!$config->getName()) {
throw new \InvalidArgumentException("MockConfiguration must contain a name");
}
$this->config = $config;
$this->code = $code;
}
public function getConfig()
{
return $this->config;
}
public function getClassName()
{
return $this->config->getName();
}
public function getCode()
{
return $this->code;
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class MockNameBuilder
{
protected static $mockCounter = 0;
protected $parts = [];
public function addPart($part)
{
$this->parts[] = $part;
return $this;
}
public function build()
{
$parts = ['Mockery', static::$mockCounter++];
foreach ($this->parts as $part) {
$parts[] = str_replace("\\", "_", $part);
}
return implode('_', $parts);
}
}

View File

@@ -0,0 +1,117 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
use Mockery\Reflector;
class Parameter
{
/** @var int */
private static $parameterCounter = 0;
/** @var \ReflectionParameter */
private $rfp;
public function __construct(\ReflectionParameter $rfp)
{
$this->rfp = $rfp;
}
public function __call($method, array $args)
{
return call_user_func_array(array($this->rfp, $method), $args);
}
/**
* Get the reflection class for the parameter type, if it exists.
*
* This will be null if there was no type, or it was a scalar or a union.
*
* @return \ReflectionClass|null
*
* @deprecated since 1.3.3 and will be removed in 2.0.
*/
public function getClass()
{
$typeHint = Reflector::getTypeHint($this->rfp, true);
return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
}
/**
* Get the string representation for the paramater type.
*
* @return string|null
*/
public function getTypeHint()
{
return Reflector::getTypeHint($this->rfp);
}
/**
* Get the string representation for the paramater type.
*
* @return string
*
* @deprecated since 1.3.2 and will be removed in 2.0. Use getTypeHint() instead.
*/
public function getTypeHintAsString()
{
return (string) Reflector::getTypeHint($this->rfp, true);
}
/**
* Get the name of the parameter.
*
* Some internal classes have funny looking definitions!
*
* @return string
*/
public function getName()
{
$name = $this->rfp->getName();
if (!$name || $name == '...') {
$name = 'arg' . self::$parameterCounter++;
}
return $name;
}
/**
* Determine if the parameter is an array.
*
* @return bool
*/
public function isArray()
{
return Reflector::isArray($this->rfp);
}
/**
* Determine if the parameter is variadic.
*
* @return bool
*/
public function isVariadic()
{
return $this->rfp->isVariadic();
}
}

View File

@@ -0,0 +1,49 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\Method;
use Mockery\Generator\Parameter;
use Mockery\Generator\MockConfiguration;
class AvoidMethodClashPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
$names = array_map(function ($method) {
return $method->getName();
}, $config->getMethodsToMock());
foreach (["allows", "expects"] as $method) {
if (in_array($method, $names)) {
$code = preg_replace(
"#// start method {$method}.*// end method {$method}#ms",
"",
$code
);
$code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code);
}
}
return $code;
}
}

View File

@@ -0,0 +1,47 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class CallTypeHintPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
if ($config->requiresCallTypeHintRemoval()) {
$code = str_replace(
'public function __call($method, array $args)',
'public function __call($method, $args)',
$code
);
}
if ($config->requiresCallStaticTypeHintRemoval()) {
$code = str_replace(
'public static function __callStatic($method, array $args)',
'public static function __callStatic($method, $args)',
$code
);
}
return $code;
}
}

View File

@@ -0,0 +1,49 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class ClassNamePass implements Pass
{
public function apply($code, MockConfiguration $config)
{
$namespace = $config->getNamespaceName();
$namespace = ltrim($namespace, "\\");
$className = $config->getShortName();
$code = str_replace(
'namespace Mockery;',
$namespace ? 'namespace ' . $namespace . ';' : '',
$code
);
$code = str_replace(
'class Mock',
'class ' . $className,
$code
);
return $code;
}
}

View File

@@ -0,0 +1,53 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class ClassPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
return $code;
}
if ($target->isFinal()) {
return $code;
}
$className = ltrim($target->getName(), "\\");
if (!class_exists($className)) {
\Mockery::declareClass($className);
}
$code = str_replace(
"implements MockInterface",
"extends \\" . $className . " implements MockInterface",
$code
);
return $code;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class ConstantsPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
$cm = $config->getConstantsMap();
if (empty($cm)) {
return $code;
}
if (!isset($cm[$config->getName()])) {
return $code;
}
$cm = $cm[$config->getName()];
$constantsCode = '';
foreach ($cm as $constant => $value) {
$constantsCode .= sprintf("\n const %s = %s;\n", $constant, var_export($value, true));
}
$i = strrpos($code, '}');
$code = substr_replace($code, $constantsCode, $i);
$code .= "}\n";
return $code;
}
}

View File

@@ -0,0 +1,83 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class InstanceMockPass
{
const INSTANCE_MOCK_CODE = <<<MOCK
protected \$_mockery_ignoreVerification = true;
public function __construct()
{
\$this->_mockery_ignoreVerification = false;
\$associatedRealObject = \Mockery::fetchMock(__CLASS__);
foreach (get_object_vars(\$this) as \$attr => \$val) {
if (\$attr !== "_mockery_ignoreVerification" && \$attr !== "_mockery_expectations") {
\$this->\$attr = \$associatedRealObject->\$attr;
}
}
\$directors = \$associatedRealObject->mockery_getExpectations();
foreach (\$directors as \$method=>\$director) {
// get the director method needed
\$existingDirector = \$this->mockery_getExpectationsFor(\$method);
if (!\$existingDirector) {
\$existingDirector = new \Mockery\ExpectationDirector(\$method, \$this);
\$this->mockery_setExpectationsFor(\$method, \$existingDirector);
}
\$expectations = \$director->getExpectations();
foreach (\$expectations as \$expectation) {
\$clonedExpectation = clone \$expectation;
\$existingDirector->addExpectation(\$clonedExpectation);
}
\$defaultExpectations = \$director->getDefaultExpectations();
foreach (array_reverse(\$defaultExpectations) as \$expectation) {
\$clonedExpectation = clone \$expectation;
\$existingDirector->addExpectation(\$clonedExpectation);
\$existingDirector->makeExpectationDefault(\$clonedExpectation);
}
}
\Mockery::getContainer()->rememberMock(\$this);
\$this->_mockery_constructorCalled(func_get_args());
}
MOCK;
public function apply($code, MockConfiguration $config)
{
if ($config->isInstanceMock()) {
$code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
}
return $code;
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
}
}

View File

@@ -0,0 +1,48 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class InterfacePass implements Pass
{
public function apply($code, MockConfiguration $config)
{
foreach ($config->getTargetInterfaces() as $i) {
$name = ltrim($i->getName(), "\\");
if (!interface_exists($name)) {
\Mockery::declareInterface($name);
}
}
$interfaces = array_reduce((array) $config->getTargetInterfaces(), function ($code, $i) {
return $code . ", \\" . ltrim($i->getName(), "\\");
}, "");
$code = str_replace(
"implements MockInterface",
"implements MockInterface" . $interfaces,
$code
);
return $code;
}
}

View File

@@ -0,0 +1,212 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\TargetClassInterface;
use Mockery\Generator\Method;
use Mockery\Generator\Parameter;
class MagicMethodTypeHintsPass implements Pass
{
/**
* @var array $mockMagicMethods
*/
private $mockMagicMethods = array(
'__construct',
'__destruct',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__sleep',
'__wakeup',
'__toString',
'__invoke',
'__set_state',
'__clone',
'__debugInfo'
);
/**
* Apply implementation.
*
* @param string $code
* @param MockConfiguration $config
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$magicMethods = $this->getMagicMethods($config->getTargetClass());
foreach ($config->getTargetInterfaces() as $interface) {
$magicMethods = array_merge($magicMethods, $this->getMagicMethods($interface));
}
foreach ($magicMethods as $method) {
$code = $this->applyMagicTypeHints($code, $method);
}
return $code;
}
/**
* Returns the magic methods within the
* passed DefinedTargetClass.
*
* @param TargetClassInterface $class
* @return array
*/
public function getMagicMethods(
TargetClassInterface $class = null
) {
if (is_null($class)) {
return array();
}
return array_filter($class->getMethods(), function (Method $method) {
return in_array($method->getName(), $this->mockMagicMethods);
});
}
/**
* Applies type hints of magic methods from
* class to the passed code.
*
* @param int $code
* @param Method $method
* @return string
*/
private function applyMagicTypeHints($code, Method $method)
{
if ($this->isMethodWithinCode($code, $method)) {
$namedParameters = $this->getOriginalParameters(
$code,
$method
);
$code = preg_replace(
$this->getDeclarationRegex($method->getName()),
$this->getMethodDeclaration($method, $namedParameters),
$code
);
}
return $code;
}
/**
* Checks if the method is declared within code.
*
* @param int $code
* @param Method $method
* @return boolean
*/
private function isMethodWithinCode($code, Method $method)
{
return preg_match(
$this->getDeclarationRegex($method->getName()),
$code
) == 1;
}
/**
* Returns the method original parameters, as they're
* described in the $code string.
*
* @param int $code
* @param Method $method
* @return array
*/
private function getOriginalParameters($code, Method $method)
{
$matches = [];
$parameterMatches = [];
preg_match(
$this->getDeclarationRegex($method->getName()),
$code,
$matches
);
if (count($matches) > 0) {
preg_match_all(
'/(?<=\$)(\w+)+/i',
$matches[0],
$parameterMatches
);
}
$groupMatches = end($parameterMatches);
$parameterNames = is_array($groupMatches) ? $groupMatches : [$groupMatches];
return $parameterNames;
}
/**
* Gets the declaration code, as a string, for the passed method.
*
* @param Method $method
* @param array $namedParameters
* @return string
*/
private function getMethodDeclaration(
Method $method,
array $namedParameters
) {
$declaration = 'public';
$declaration .= $method->isStatic() ? ' static' : '';
$declaration .= ' function ' . $method->getName() . '(';
foreach ($method->getParameters() as $index => $parameter) {
$declaration .= $this->renderTypeHint($parameter);
$name = isset($namedParameters[$index]) ? $namedParameters[$index] : $parameter->getName();
$declaration .= '$' . $name;
$declaration .= ',';
}
$declaration = rtrim($declaration, ',');
$declaration .= ') ';
$returnType = $method->getReturnType();
if ($returnType !== null) {
$declaration .= sprintf(': %s', $returnType);
}
return $declaration;
}
protected function renderTypeHint(Parameter $param)
{
$typeHint = $param->getTypeHint();
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
}
/**
* Returns a regex string used to match the
* declaration of some method.
*
* @param string $methodName
* @return string
*/
private function getDeclarationRegex($methodName)
{
return "/public\s+(?:static\s+)?function\s+$methodName\s*\(.*\)\s*(?=\{)/i";
}
}

View File

@@ -0,0 +1,167 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\Method;
use Mockery\Generator\Parameter;
use Mockery\Generator\MockConfiguration;
class MethodDefinitionPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
foreach ($config->getMethodsToMock() as $method) {
if ($method->isPublic()) {
$methodDef = 'public';
} elseif ($method->isProtected()) {
$methodDef = 'protected';
} else {
$methodDef = 'private';
}
if ($method->isStatic()) {
$methodDef .= ' static';
}
$methodDef .= ' function ';
$methodDef .= $method->returnsReference() ? ' & ' : '';
$methodDef .= $method->getName();
$methodDef .= $this->renderParams($method, $config);
$methodDef .= $this->renderReturnType($method);
$methodDef .= $this->renderMethodBody($method, $config);
$code = $this->appendToClass($code, $methodDef);
}
return $code;
}
protected function renderParams(Method $method, $config)
{
$class = $method->getDeclaringClass();
if ($class->isInternal()) {
$overrides = $config->getParameterOverrides();
if (isset($overrides[strtolower($class->getName())][$method->getName()])) {
return '(' . implode(',', $overrides[strtolower($class->getName())][$method->getName()]) . ')';
}
}
$methodParams = array();
$params = $method->getParameters();
foreach ($params as $param) {
$paramDef = $this->renderTypeHint($param);
$paramDef .= $param->isPassedByReference() ? '&' : '';
$paramDef .= $param->isVariadic() ? '...' : '';
$paramDef .= '$' . $param->getName();
if (!$param->isVariadic()) {
if (false !== $param->isDefaultValueAvailable()) {
$defaultValue = $param->getDefaultValue();
$paramDef .= ' = ' . (is_object($defaultValue) ? get_class($defaultValue) : var_export($defaultValue, true));
} elseif ($param->isOptional()) {
$paramDef .= ' = null';
}
}
$methodParams[] = $paramDef;
}
return '(' . implode(', ', $methodParams) . ')';
}
protected function renderReturnType(Method $method)
{
$type = $method->getReturnType();
return $type ? sprintf(': %s', $type) : '';
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
}
protected function renderTypeHint(Parameter $param)
{
$typeHint = $param->getTypeHint();
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
}
private function renderMethodBody($method, $config)
{
$invoke = $method->isStatic() ? 'static::_mockery_handleStaticMethodCall' : '$this->_mockery_handleMethodCall';
$body = <<<BODY
{
\$argc = func_num_args();
\$argv = func_get_args();
BODY;
// Fix up known parameters by reference - used func_get_args() above
// in case more parameters are passed in than the function definition
// says - eg varargs.
$class = $method->getDeclaringClass();
$class_name = strtolower($class->getName());
$overrides = $config->getParameterOverrides();
if (isset($overrides[$class_name][$method->getName()])) {
$params = array_values($overrides[$class_name][$method->getName()]);
$paramCount = count($params);
for ($i = 0; $i < $paramCount; ++$i) {
$param = $params[$i];
if (strpos($param, '&') !== false) {
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] = {$param};
}
BODY;
}
}
} else {
$params = array_values($method->getParameters());
$paramCount = count($params);
for ($i = 0; $i < $paramCount; ++$i) {
$param = $params[$i];
if (!$param->isPassedByReference()) {
continue;
}
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] =& \${$param->getName()};
}
BODY;
}
}
$body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n";
if ($method->getReturnType() !== "void") {
$body .= "return \$ret;\n";
}
$body .= "}\n";
return $body;
}
}

View File

@@ -0,0 +1,28 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
interface Pass
{
public function apply($code, MockConfiguration $config);
}

View File

@@ -0,0 +1,53 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
/**
* The standard Mockery\Mock class includes some methods to ease mocking, such
* as __wakeup, however if the target has a final __wakeup method, it can't be
* mocked. This pass removes the builtin methods where they are final on the
* target
*/
class RemoveBuiltinMethodsThatAreFinalPass
{
protected $methods = array(
'__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm',
);
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
return $code;
}
foreach ($target->getMethods() as $method) {
if ($method->isFinal() && isset($this->methods[$method->getName()])) {
$code = preg_replace($this->methods[$method->getName()], '', $code);
}
}
return $code;
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @author Boris Avdeev <elephant@lislon.ru>
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
/**
* Remove mock's empty destructor if we tend to use original class destructor
*/
class RemoveDestructorPass
{
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
return $code;
}
if (!$config->isMockOriginalDestructor()) {
$code = preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code);
}
return $code;
}
}

View File

@@ -0,0 +1,59 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
/**
* Internal classes can not be instantiated with the newInstanceWithoutArgs
* reflection method, so need the serialization hack. If the class also
* implements Serializable, we need to replace the standard unserialize method
* definition with a dummy
*/
class RemoveUnserializeForInternalSerializableClassesPass
{
const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} ';
const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} ';
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
return $code;
}
if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) {
return $code;
}
$code = $this->appendToClass($code, \PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION);
return $code;
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
}
}

View File

@@ -0,0 +1,47 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
class TraitPass implements Pass
{
public function apply($code, MockConfiguration $config)
{
$traits = $config->getTargetTraits();
if (empty($traits)) {
return $code;
}
$useStatements = array_map(function ($trait) {
return "use \\\\" . ltrim($trait->getName(), "\\") . ";";
}, $traits);
$code = preg_replace(
'/^{$/m',
"{\n " . implode("\n ", $useStatements) . "\n",
$code
);
return $code;
}
}

View File

@@ -0,0 +1,89 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
use Mockery\Generator\StringManipulation\Pass\ClassPass;
use Mockery\Generator\StringManipulation\Pass\ConstantsPass;
use Mockery\Generator\StringManipulation\Pass\InstanceMockPass;
use Mockery\Generator\StringManipulation\Pass\InterfacePass;
use Mockery\Generator\StringManipulation\Pass\MagicMethodTypeHintsPass;
use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass;
use Mockery\Generator\StringManipulation\Pass\Pass;
use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass;
use Mockery\Generator\StringManipulation\Pass\RemoveDestructorPass;
use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass;
use Mockery\Generator\StringManipulation\Pass\TraitPass;
use Mockery\Generator\StringManipulation\Pass\AvoidMethodClashPass;
class StringManipulationGenerator implements Generator
{
protected $passes = array();
/**
* Creates a new StringManipulationGenerator with the default passes
*
* @return StringManipulationGenerator
*/
public static function withDefaultPasses()
{
return new static([
new CallTypeHintPass(),
new MagicMethodTypeHintsPass(),
new ClassPass(),
new TraitPass(),
new ClassNamePass(),
new InstanceMockPass(),
new InterfacePass(),
new AvoidMethodClashPass(),
new MethodDefinitionPass(),
new RemoveUnserializeForInternalSerializableClassesPass(),
new RemoveBuiltinMethodsThatAreFinalPass(),
new RemoveDestructorPass(),
new ConstantsPass(),
]);
}
public function __construct(array $passes)
{
$this->passes = $passes;
}
public function generate(MockConfiguration $config)
{
$code = file_get_contents(__DIR__ . '/../Mock.php');
$className = $config->getName() ?: $config->generateName();
$namedConfig = $config->rename($className);
foreach ($this->passes as $pass) {
$code = $pass->apply($code, $namedConfig);
}
return new MockDefinition($namedConfig, $code);
}
public function addPass(Pass $pass)
{
$this->passes[] = $pass;
}
}

View File

@@ -0,0 +1,107 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
interface TargetClassInterface
{
/**
* Returns a new instance of the current
* TargetClassInterface's
* implementation.
*
* @param string $name
* @return TargetClassInterface
*/
public static function factory($name);
/**
* Returns the targetClass's name.
*
* @return string
*/
public function getName();
/**
* Returns the targetClass's methods.
*
* @return array
*/
public function getMethods();
/**
* Returns the targetClass's interfaces.
*
* @return array
*/
public function getInterfaces();
/**
* Returns the targetClass's namespace name.
*
* @return string
*/
public function getNamespaceName();
/**
* Returns the targetClass's short name.
*
* @return string
*/
public function getShortName();
/**
* Returns whether the targetClass is abstract.
*
* @return boolean
*/
public function isAbstract();
/**
* Returns whether the targetClass is final.
*
* @return boolean
*/
public function isFinal();
/**
* Returns whether the targetClass is in namespace.
*
* @return boolean
*/
public function inNamespace();
/**
* Returns whether the targetClass is in
* the passed interface.
*
* @param mixed $interface
* @return boolean
*/
public function implementsInterface($interface);
/**
* Returns whether the targetClass has
* an internal ancestor.
*
* @return boolean
*/
public function hasInternalAncestor();
}

View File

@@ -0,0 +1,94 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Generator;
class UndefinedTargetClass implements TargetClassInterface
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public static function factory($name)
{
return new self($name);
}
public function getName()
{
return $this->name;
}
public function isAbstract()
{
return false;
}
public function isFinal()
{
return false;
}
public function getMethods()
{
return array();
}
public function getInterfaces()
{
return array();
}
public function getNamespaceName()
{
$parts = explode("\\", ltrim($this->getName(), "\\"));
array_pop($parts);
return implode("\\", $parts);
}
public function inNamespace()
{
return $this->getNamespaceName() !== '';
}
public function getShortName()
{
$parts = explode("\\", $this->getName());
return array_pop($parts);
}
public function implementsInterface($interface)
{
return false;
}
public function hasInternalAncestor()
{
return false;
}
public function __toString()
{
return $this->name;
}
}

View File

@@ -0,0 +1,49 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
/**
* @method \Mockery\Expectation withArgs(\Closure|array $args)
*/
class HigherOrderMessage
{
private $mock;
private $method;
public function __construct(MockInterface $mock, $method)
{
$this->mock = $mock;
$this->method = $method;
}
/**
* @return \Mockery\Expectation
*/
public function __call($method, $args)
{
if ($this->method === 'shouldNotHaveReceived') {
return $this->mock->{$this->method}($method, $args);
}
$expectation = $this->mock->{$this->method}($method);
return $expectation->withArgs($args);
}
}

View File

@@ -0,0 +1,162 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Mockery;
use Closure;
use ReflectionClass;
use UnexpectedValueException;
use InvalidArgumentException;
/**
* This is a trimmed down version of https://github.com/doctrine/instantiator,
* basically without the caching
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
final class Instantiator
{
/**
* {@inheritDoc}
*/
public function instantiate($className)
{
$factory = $this->buildFactory($className);
$instance = $factory();
return $instance;
}
/**
* Builds a {@see \Closure} capable of instantiating the given $className without
* invoking its constructor.
*
* @param string $className
*
* @return Closure
*/
private function buildFactory($className)
{
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return function () use ($reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
};
}
$serializedString = sprintf(
'O:%d:"%s":0:{}',
strlen($className),
$className
);
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
return function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @param string $className
*
* @return ReflectionClass
*
* @throws InvalidArgumentException
*/
private function getReflectionClass($className)
{
if (! class_exists($className)) {
throw new InvalidArgumentException("Class:$className does not exist");
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw new InvalidArgumentException("Class:$className is an abstract class");
}
return $reflection;
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString)
{
set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) {
$msg = sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered in file "%s" at line "%d"',
$reflectionClass->getName(),
$file,
$line
);
$error = new UnexpectedValueException($msg, 0, new \Exception($message, $code));
});
try {
unserialize($serializedString);
} catch (\Exception $exception) {
restore_error_handler();
throw new UnexpectedValueException("An exception was raised while trying to instantiate an instance of \"{$reflectionClass->getName()}\" via un-serialization", 0, $exception);
}
restore_error_handler();
if ($error) {
throw $error;
}
}
/**
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass)
{
return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
}
/**
* Verifies whether the given class is to be considered internal
*
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass)
{
do {
if ($reflectionClass->isInternal()) {
return true;
}
} while ($reflectionClass = $reflectionClass->getParentClass());
return false;
}
}

View File

@@ -0,0 +1,240 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
interface LegacyMockInterface
{
/**
* Alternative setup method to constructor
*
* @param \Mockery\Container $container
* @param object $partialObject
* @return void
*/
public function mockery_init(\Mockery\Container $container = null, $partialObject = null);
/**
* Set expected method calls
*
* @param string|array ...$methodNames one or many methods that are expected to be called in this mock
*
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldReceive(...$methodNames);
/**
* Shortcut method for setting an expectation that a method should not be called.
*
* @param string|array ...$methodNames one or many methods that are expected not to be called in this mock
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames);
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
* @param String $method name of the method to be mocked
*/
public function shouldAllowMockingMethod($method);
/**
* Set mock to ignore unexpected methods and return Undefined class
* @param mixed $returnValue the default return value for calls to missing functions on this mock
* @return Mock
*/
public function shouldIgnoreMissing($returnValue = null);
/**
* @return Mock
*/
public function shouldAllowMockingProtectedMethods();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return Mock
*/
public function shouldDeferMissing();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @return Mock
*/
public function makePartial();
/**
* @param null|string $method
* @param null|array|Closure $args
* @return mixed
*/
public function shouldHaveReceived($method, $args = null);
/**
* @return mixed
*/
public function shouldHaveBeenCalled();
/**
* @param null|string $method
* @param null|array|Closure $args
* @return mixed
*/
public function shouldNotHaveReceived($method, $args = null);
/**
* @param array $args (optional)
* @return mixed
*/
public function shouldNotHaveBeenCalled(array $args = null);
/**
* In the event shouldReceive() accepting an array of methods/returns
* this method will switch them from normal expectations to default
* expectations
*
* @return self
*/
public function byDefault();
/**
* Iterate across all expectation directors and validate each
*
* @throws \Mockery\CountValidator\Exception
* @return void
*/
public function mockery_verify();
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown();
/**
* Fetch the next available allocation order number
*
* @return int
*/
public function mockery_allocateOrder();
/**
* Set ordering for a group
*
* @param mixed $group
* @param int $order
*/
public function mockery_setGroup($group, $order);
/**
* Fetch array of ordered groups
*
* @return array
*/
public function mockery_getGroups();
/**
* Set current ordered number
*
* @param int $order
*/
public function mockery_setCurrentOrder($order);
/**
* Get current ordered number
*
* @return int
*/
public function mockery_getCurrentOrder();
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
* @throws \Mockery\Exception
* @return void
*/
public function mockery_validateOrder($method, $order);
/**
* Gets the count of expectations for this mock
*
* @return int
*/
public function mockery_getExpectationCount();
/**
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
*/
public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director);
/**
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
*/
public function mockery_getExpectationsFor($method);
/**
* Find an expectation matching the given method and arguments
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
*/
public function mockery_findExpectation($method, array $args);
/**
* Return the container for this mock
*
* @return \Mockery\Container
*/
public function mockery_getContainer();
/**
* Return the name for this mock
*
* @return string
*/
public function mockery_getName();
/**
* @return array
*/
public function mockery_getMockableProperties();
/**
* @return string[]
*/
public function mockery_getMockableMethods();
/**
* @return bool
*/
public function mockery_isAnonymous();
}

View File

@@ -0,0 +1,36 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Loader;
use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;
class EvalLoader implements Loader
{
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
eval("?>" . $definition->getCode());
}
}

View File

@@ -0,0 +1,28 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Loader;
use Mockery\Generator\MockDefinition;
interface Loader
{
public function load(MockDefinition $definition);
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Loader;
use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;
class RequireLoader implements Loader
{
protected $path;
public function __construct($path = null)
{
$this->path = realpath($path) ?: sys_get_temp_dir();
}
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
$tmpfname = $this->path . DIRECTORY_SEPARATOR . "Mockery_" . uniqid() . ".php";
file_put_contents($tmpfname, $definition->getCode());
require $tmpfname;
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class AndAnyOtherArgs extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<AndAnyOthers>';
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Any extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<Any>';
}
}

View File

@@ -0,0 +1,40 @@
<?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) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class AnyArgs extends MatcherAbstract implements ArgumentListMatcher
{
/**
* @inheritdoc
*/
public function match(&$actual)
{
return true;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<Any Arguments>';
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class AnyOf extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return in_array($actual, $this->_expected, true);
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<AnyOf>';
}
}

View File

@@ -0,0 +1,25 @@
<?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) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
interface ArgumentListMatcher
{
}

View File

@@ -0,0 +1,47 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Closure extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
$closure = $this->_expected;
$result = $closure($actual);
return $result === true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<Closure===true>';
}
}

View File

@@ -0,0 +1,64 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Contains extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
$values = array_values($actual);
foreach ($this->_expected as $exp) {
$match = false;
foreach ($values as $val) {
if ($exp === $val || $exp == $val) {
$match = true;
break;
}
}
if ($match === false) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$return = '<Contains[';
$elements = array();
foreach ($this->_expected as $v) {
$elements[] = (string) $v;
}
$return .= implode(', ', $elements) . ']>';
return $return;
}
}

View File

@@ -0,0 +1,53 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Ducktype extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if (!is_object($actual)) {
return false;
}
foreach ($this->_expected as $method) {
if (!method_exists($actual, $method)) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<Ducktype[' . implode(', ', $this->_expected) . ']>';
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class HasKey extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return array_key_exists($this->_expected, $actual);
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return "<HasKey[$this->_expected]>";
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class HasValue extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return in_array($this->_expected, $actual);
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$return = '<HasValue[' . (string) $this->_expected . ']>';
return $return;
}
}

View File

@@ -0,0 +1,58 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
abstract class MatcherAbstract
{
/**
* The expected value (or part thereof)
*
* @var mixed
*/
protected $_expected = null;
/**
* Set the expected value
*
* @param mixed $expected
*/
public function __construct($expected = null)
{
$this->_expected = $expected;
}
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @param mixed $actual
* @return bool
*/
abstract public function match(&$actual);
/**
* Return a string representation of this Matcher
*
* @return string
*/
abstract public function __toString();
}

View File

@@ -0,0 +1,48 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class MultiArgumentClosure extends MatcherAbstract implements ArgumentListMatcher
{
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
$closure = $this->_expected;
return true === call_user_func_array($closure, $actual);
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<MultiArgumentClosure===true>';
}
}

View File

@@ -0,0 +1,52 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
/**
* @deprecated 2.0 Due to ambiguity, use Hamcrest or PHPUnit equivalents
*/
class MustBe extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if (!is_object($actual)) {
return $this->_expected === $actual;
}
return $this->_expected == $actual;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<MustBe>';
}
}

View File

@@ -0,0 +1,40 @@
<?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) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class NoArgs extends MatcherAbstract implements ArgumentListMatcher
{
/**
* @inheritdoc
*/
public function match(&$actual)
{
return count($actual) == 0;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<No Arguments>';
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Not extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return $actual !== $this->_expected;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<Not>';
}
}

View File

@@ -0,0 +1,51 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class NotAnyOf extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
foreach ($this->_expected as $exp) {
if ($actual === $exp || $actual == $exp) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<AnyOf>';
}
}

View File

@@ -0,0 +1,45 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Pattern extends MatcherAbstract
{
/**
* Check if the actual value matches the expected pattern.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return preg_match($this->_expected, (string) $actual) >= 1;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<Pattern>';
}
}

View File

@@ -0,0 +1,92 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Subset extends MatcherAbstract
{
private $expected;
private $strict = true;
/**
* @param array $expected Expected subset of data
* @param bool $strict Whether to run a strict or loose comparison
*/
public function __construct(array $expected, $strict = true)
{
$this->expected = $expected;
$this->strict = $strict;
}
/**
* @param array $expected Expected subset of data
*
* @return Subset
*/
public static function strict(array $expected)
{
return new static($expected, true);
}
/**
* @param array $expected Expected subset of data
*
* @return Subset
*/
public static function loose(array $expected)
{
return new static($expected, false);
}
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if (!is_array($actual)) {
return false;
}
if ($this->strict) {
return $actual === array_replace_recursive($actual, $this->expected);
}
return $actual == array_replace_recursive($actual, $this->expected);
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$return = '<Subset[';
$elements = array();
foreach ($this->expected as $k=>$v) {
$elements[] = $k . '=' . (string) $v;
}
$return .= implode(', ', $elements) . ']>';
return $return;
}
}

View File

@@ -0,0 +1,56 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Matcher;
class Type extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if ($this->_expected == 'real') {
$function = 'is_float';
} else {
$function = 'is_' . strtolower($this->_expected);
}
if (function_exists($function)) {
return $function($actual);
} elseif (is_string($this->_expected)
&& (class_exists($this->_expected) || interface_exists($this->_expected))) {
return $actual instanceof $this->_expected;
}
return false;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
return '<' . ucfirst($this->_expected) . '>';
}
}

View File

@@ -0,0 +1,43 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class MethodCall
{
private $method;
private $args;
public function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
public function getMethod()
{
return $this->method;
}
public function getArgs()
{
return $this->args;
}
}

View File

@@ -0,0 +1,977 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
use Mockery\Exception\BadMethodCallException;
use Mockery\ExpectsHigherOrderMessage;
use Mockery\HigherOrderMessage;
use Mockery\LegacyMockInterface;
use Mockery\MockInterface;
use Mockery\Reflector;
class Mock implements MockInterface
{
/**
* Stores an array of all expectation directors for this mock
*
* @var array
*/
protected $_mockery_expectations = array();
/**
* Stores an initial number of expectations that can be manipulated
* while using the getter method.
*
* @var int
*/
protected $_mockery_expectations_count = 0;
/**
* Flag to indicate whether we can ignore method calls missing from our
* expectations
*
* @var bool
*/
protected $_mockery_ignoreMissing = false;
/**
* Flag to indicate whether we want to set the ignoreMissing flag on
* mocks generated form this calls to this one
*
* @var bool
*/
protected $_mockery_ignoreMissingRecursive = false;
/**
* Flag to indicate whether we can defer method calls missing from our
* expectations
*
* @var bool
*/
protected $_mockery_deferMissing = false;
/**
* Flag to indicate whether this mock was verified
*
* @var bool
*/
protected $_mockery_verified = false;
/**
* Given name of the mock
*
* @var string
*/
protected $_mockery_name = null;
/**
* Order number of allocation
*
* @var int
*/
protected $_mockery_allocatedOrder = 0;
/**
* Current ordered number
*
* @var int
*/
protected $_mockery_currentOrder = 0;
/**
* Ordered groups
*
* @var array
*/
protected $_mockery_groups = array();
/**
* Mock container containing this mock object
*
* @var \Mockery\Container
*/
protected $_mockery_container = null;
/**
* Instance of a core object on which methods are called in the event
* it has been set, and an expectation for one of the object's methods
* does not exist. This implements a simple partial mock proxy system.
*
* @var object
*/
protected $_mockery_partial = null;
/**
* Flag to indicate we should ignore all expectations temporarily. Used
* mainly to prevent expectation matching when in the middle of a mock
* object recording session.
*
* @var bool
*/
protected $_mockery_disableExpectationMatching = false;
/**
* Stores all stubbed public methods separate from any on-object public
* properties that may exist.
*
* @var array
*/
protected $_mockery_mockableProperties = array();
/**
* @var array
*/
protected $_mockery_mockableMethods = array();
/**
* Just a local cache for this mock's target's methods
*
* @var \ReflectionMethod[]
*/
protected static $_mockery_methods;
protected $_mockery_allowMockingProtectedMethods = false;
protected $_mockery_receivedMethodCalls;
/**
* If shouldIgnoreMissing is called, this value will be returned on all calls to missing methods
* @var mixed
*/
protected $_mockery_defaultReturnValue = null;
/**
* Tracks internally all the bad method call exceptions that happened during runtime
*
* @var array
*/
protected $_mockery_thrownExceptions = [];
protected $_mockery_instanceMock = true;
/**
* We want to avoid constructors since class is copied to Generator.php
* for inclusion on extending class definitions.
*
* @param \Mockery\Container $container
* @param object $partialObject
* @param bool $instanceMock
* @return void
*/
public function mockery_init(\Mockery\Container $container = null, $partialObject = null, $instanceMock = true)
{
if (is_null($container)) {
$container = new \Mockery\Container();
}
$this->_mockery_container = $container;
if (!is_null($partialObject)) {
$this->_mockery_partial = $partialObject;
}
if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
foreach ($this->mockery_getMethods() as $method) {
if ($method->isPublic()) {
$this->_mockery_mockableMethods[] = $method->getName();
}
}
}
$this->_mockery_instanceMock = $instanceMock;
}
/**
* Set expected method calls
*
* @param string ...$methodNames one or many methods that are expected to be called in this mock
*
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldReceive");
}
foreach ($methodNames as $method) {
if ("" == $method) {
throw new \InvalidArgumentException("Received empty method name");
}
}
$self = $this;
$allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;
$lastExpectation = \Mockery::parseShouldReturnArgs(
$this,
$methodNames,
function ($method) use ($self, $allowMockingProtectedMethods) {
$rm = $self->mockery_getMethod($method);
if ($rm) {
if ($rm->isPrivate()) {
throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method");
}
if (!$allowMockingProtectedMethods && $rm->isProtected()) {
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. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods.");
}
}
$director = $self->mockery_getExpectationsFor($method);
if (!$director) {
$director = new \Mockery\ExpectationDirector($method, $self);
$self->mockery_setExpectationsFor($method, $director);
}
$expectation = new \Mockery\Expectation($self, $method);
$director->addExpectation($expectation);
return $expectation;
}
);
return $lastExpectation;
}
// start method allows
/**
* @param mixed $something String method name or map of method => return
* @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function allows($something = [])
{
if (is_string($something)) {
return $this->shouldReceive($something);
}
if (empty($something)) {
return $this->shouldReceive();
}
foreach ($something as $method => $returnValue) {
$this->shouldReceive($method)->andReturn($returnValue);
}
return $this;
}
// end method allows
// start method expects
/**
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|ExpectsHigherOrderMessage
*/
public function expects($something = null)
{
if (is_string($something)) {
return $this->shouldReceive($something)->once();
}
return new ExpectsHigherOrderMessage($this);
}
// end method expects
/**
* Shortcut method for setting an expectation that a method should not be called.
*
* @param string ...$methodNames one or many methods that are expected not to be called in this mock
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldNotReceive");
}
$expectation = call_user_func_array(array($this, 'shouldReceive'), $methodNames);
$expectation->never();
return $expectation;
}
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
* @param String $method name of the method to be mocked
* @return Mock
*/
public function shouldAllowMockingMethod($method)
{
$this->_mockery_mockableMethods[] = $method;
return $this;
}
/**
* Set mock to ignore unexpected methods and return Undefined class
* @param mixed $returnValue the default return value for calls to missing functions on this mock
* @param bool $recursive Specify if returned mocks should also have shouldIgnoreMissing set
* @return Mock
*/
public function shouldIgnoreMissing($returnValue = null, $recursive = false)
{
$this->_mockery_ignoreMissing = true;
$this->_mockery_ignoreMissingRecursive = $recursive;
$this->_mockery_defaultReturnValue = $returnValue;
return $this;
}
public function asUndefined()
{
$this->_mockery_ignoreMissing = true;
$this->_mockery_defaultReturnValue = new \Mockery\Undefined();
return $this;
}
/**
* @return Mock
*/
public function shouldAllowMockingProtectedMethods()
{
if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
foreach ($this->mockery_getMethods() as $method) {
if ($method->isProtected()) {
$this->_mockery_mockableMethods[] = $method->getName();
}
}
}
$this->_mockery_allowMockingProtectedMethods = true;
return $this;
}
/**
* Set mock to defer unexpected methods to it's parent
*
* This is particularly useless for this class, as it doesn't have a parent,
* but included for completeness
*
* @deprecated 2.0.0 Please use makePartial() instead
*
* @return Mock
*/
public function shouldDeferMissing()
{
return $this->makePartial();
}
/**
* Set mock to defer unexpected methods to it's parent
*
* It was an alias for shouldDeferMissing(), which will be removed
* in 2.0.0.
*
* @return Mock
*/
public function makePartial()
{
$this->_mockery_deferMissing = true;
return $this;
}
/**
* In the event shouldReceive() accepting one or more methods/returns,
* this method will switch them from normal expectations to default
* expectations
*
* @return self
*/
public function byDefault()
{
foreach ($this->_mockery_expectations as $director) {
$exps = $director->getExpectations();
foreach ($exps as $exp) {
$exp->byDefault();
}
}
return $this;
}
/**
* Capture calls to this mock
*/
public function __call($method, array $args)
{
return $this->_mockery_handleMethodCall($method, $args);
}
public static function __callStatic($method, array $args)
{
return self::_mockery_handleStaticMethodCall($method, $args);
}
/**
* Forward calls to this magic method to the __call method
*/
public function __toString()
{
return $this->__call('__toString', array());
}
/**
* Iterate across all expectation directors and validate each
*
* @throws \Mockery\CountValidator\Exception
* @return void
*/
public function mockery_verify()
{
if ($this->_mockery_verified) {
return;
}
if (isset($this->_mockery_ignoreVerification)
&& $this->_mockery_ignoreVerification == true) {
return;
}
$this->_mockery_verified = true;
foreach ($this->_mockery_expectations as $director) {
$director->verify();
}
}
/**
* Gets a list of exceptions thrown by this mock
*
* @return array
*/
public function mockery_thrownExceptions()
{
return $this->_mockery_thrownExceptions;
}
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown()
{
}
/**
* Fetch the next available allocation order number
*
* @return int
*/
public function mockery_allocateOrder()
{
$this->_mockery_allocatedOrder += 1;
return $this->_mockery_allocatedOrder;
}
/**
* Set ordering for a group
*
* @param mixed $group
* @param int $order
*/
public function mockery_setGroup($group, $order)
{
$this->_mockery_groups[$group] = $order;
}
/**
* Fetch array of ordered groups
*
* @return array
*/
public function mockery_getGroups()
{
return $this->_mockery_groups;
}
/**
* Set current ordered number
*
* @param int $order
*/
public function mockery_setCurrentOrder($order)
{
$this->_mockery_currentOrder = $order;
return $this->_mockery_currentOrder;
}
/**
* Get current ordered number
*
* @return int
*/
public function mockery_getCurrentOrder()
{
return $this->_mockery_currentOrder;
}
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
* @throws \Mockery\Exception
* @return void
*/
public function mockery_validateOrder($method, $order)
{
if ($order < $this->_mockery_currentOrder) {
$exception = new \Mockery\Exception\InvalidOrderException(
'Method ' . __CLASS__ . '::' . $method . '()'
. ' called out of order: expected order '
. $order . ', was ' . $this->_mockery_currentOrder
);
$exception->setMock($this)
->setMethodName($method)
->setExpectedOrder($order)
->setActualOrder($this->_mockery_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
/**
* Gets the count of expectations for this mock
*
* @return int
*/
public function mockery_getExpectationCount()
{
$count = $this->_mockery_expectations_count;
foreach ($this->_mockery_expectations as $director) {
$count += $director->getExpectationCount();
}
return $count;
}
/**
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
*/
public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
{
$this->_mockery_expectations[$method] = $director;
}
/**
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
*/
public function mockery_getExpectationsFor($method)
{
if (isset($this->_mockery_expectations[$method])) {
return $this->_mockery_expectations[$method];
}
}
/**
* Find an expectation matching the given method and arguments
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
*/
public function mockery_findExpectation($method, array $args)
{
if (!isset($this->_mockery_expectations[$method])) {
return null;
}
$director = $this->_mockery_expectations[$method];
return $director->findExpectation($args);
}
/**
* Return the container for this mock
*
* @return \Mockery\Container
*/
public function mockery_getContainer()
{
return $this->_mockery_container;
}
/**
* Return the name for this mock
*
* @return string
*/
public function mockery_getName()
{
return __CLASS__;
}
/**
* @return array
*/
public function mockery_getMockableProperties()
{
return $this->_mockery_mockableProperties;
}
public function __isset($name)
{
if (false === stripos($name, '_mockery_') && get_parent_class($this) && method_exists(get_parent_class($this), '__isset')) {
return call_user_func('parent::__isset', $name);
}
return false;
}
public function mockery_getExpectations()
{
return $this->_mockery_expectations;
}
/**
* Calls a parent class method and returns the result. Used in a passthru
* expectation where a real return value is required while still taking
* advantage of expectation matching and call count verification.
*
* @param string $name
* @param array $args
* @return mixed
*/
public function mockery_callSubjectMethod($name, array $args)
{
if (!method_exists($this, $name) && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) {
return call_user_func('parent::__call', $name, $args);
}
return call_user_func_array('parent::' . $name, $args);
}
/**
* @return string[]
*/
public function mockery_getMockableMethods()
{
return $this->_mockery_mockableMethods;
}
/**
* @return bool
*/
public function mockery_isAnonymous()
{
$rfc = new \ReflectionClass($this);
// PHP 8 has Stringable interface
$interfaces = array_filter($rfc->getInterfaces(), function ($i) {
return $i->getName() !== 'Stringable';
});
return false === $rfc->getParentClass() && 2 === count($interfaces);
}
public function mockery_isInstance()
{
return $this->_mockery_instanceMock;
}
public function __wakeup()
{
/**
* This does not add __wakeup method support. It's a blind method and any
* expected __wakeup work will NOT be performed. It merely cuts off
* annoying errors where a __wakeup exists but is not essential when
* mocking
*/
}
public function __destruct()
{
/**
* Overrides real class destructor in case if class was created without original constructor
*/
}
public function mockery_getMethod($name)
{
foreach ($this->mockery_getMethods() as $method) {
if ($method->getName() == $name) {
return $method;
}
}
return null;
}
/**
* @param string $name Method name.
*
* @return mixed Generated return value based on the declared return value of the named method.
*/
public function mockery_returnValueForMethod($name)
{
$rm = $this->mockery_getMethod($name);
if ($rm === null) {
return null;
}
$returnType = Reflector::getSimplestReturnType($rm);
switch ($returnType) {
case null: return null;
case 'string': return '';
case 'int': return 0;
case 'float': return 0.0;
case 'bool': return false;
case 'array':
case 'iterable':
return [];
case 'callable':
case '\Closure':
return function () {
};
case '\Traversable':
case '\Generator':
$generator = function () { yield; };
return $generator();
case 'void':
return null;
case 'static':
return $this;
case 'object':
$mock = \Mockery::mock();
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
default:
$mock = \Mockery::mock($returnType);
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
}
}
public function shouldHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldHaveReceived");
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
if (null !== $args) {
$expectation->withArgs($args);
}
$expectation->atLeast()->once();
$director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
$this->_mockery_expectations_count++;
$director->verify();
return $director;
}
public function shouldHaveBeenCalled()
{
return $this->shouldHaveReceived("__invoke");
}
public function shouldNotHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldNotHaveReceived");
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
if (null !== $args) {
$expectation->withArgs($args);
}
$expectation->never();
$director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
$this->_mockery_expectations_count++;
$director->verify();
return null;
}
public function shouldNotHaveBeenCalled(array $args = null)
{
return $this->shouldNotHaveReceived("__invoke", $args);
}
protected static function _mockery_handleStaticMethodCall($method, array $args)
{
$associatedRealObject = \Mockery::fetchMock(__CLASS__);
try {
return $associatedRealObject->__call($method, $args);
} catch (BadMethodCallException $e) {
throw new BadMethodCallException(
'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
. '() does not exist on this mock object',
0,
$e
);
}
}
protected function _mockery_getReceivedMethodCalls()
{
return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
}
/**
* Called when an instance Mock was created and its constructor is getting called
*
* @see \Mockery\Generator\StringManipulation\Pass\InstanceMockPass
* @param array $args
*/
protected function _mockery_constructorCalled(array $args)
{
if (!isset($this->_mockery_expectations['__construct']) /* _mockery_handleMethodCall runs the other checks */) {
return;
}
$this->_mockery_handleMethodCall('__construct', $args);
}
protected function _mockery_findExpectedMethodHandler($method)
{
if (isset($this->_mockery_expectations[$method])) {
return $this->_mockery_expectations[$method];
}
$lowerCasedMockeryExpectations = array_change_key_case($this->_mockery_expectations, CASE_LOWER);
$lowerCasedMethod = strtolower($method);
if (isset($lowerCasedMockeryExpectations[$lowerCasedMethod])) {
return $lowerCasedMockeryExpectations[$lowerCasedMethod];
}
return null;
}
protected function _mockery_handleMethodCall($method, array $args)
{
$this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));
$rm = $this->mockery_getMethod($method);
if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
if ($rm->isAbstract()) {
return;
}
try {
$prototype = $rm->getPrototype();
if ($prototype->isAbstract()) {
return;
}
} catch (\ReflectionException $re) {
// noop - there is no hasPrototype method
}
return call_user_func_array("parent::$method", $args);
}
$handler = $this->_mockery_findExpectedMethodHandler($method);
if ($handler !== null && !$this->_mockery_disableExpectationMatching) {
try {
return $handler->call($args);
} catch (\Mockery\Exception\NoMatchingExpectationException $e) {
if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
throw $e;
}
}
}
if (!is_null($this->_mockery_partial) &&
(method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call'))
) {
return call_user_func_array(array($this->_mockery_partial, $method), $args);
} elseif ($this->_mockery_deferMissing && is_callable("parent::$method")
&& (!$this->hasMethodOverloadingInParentClass() || (get_parent_class($this) && method_exists(get_parent_class($this), $method)))) {
return call_user_func_array("parent::$method", $args);
} elseif ($this->_mockery_deferMissing && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) {
return call_user_func('parent::__call', $method, $args);
} elseif ($method == '__toString') {
// __toString is special because we force its addition to the class API regardless of the
// original implementation. Thus, we should always return a string rather than honor
// _mockery_ignoreMissing and break the API with an error.
return sprintf("%s#%s", __CLASS__, spl_object_hash($this));
} elseif ($this->_mockery_ignoreMissing) {
if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable("parent::$method")) {
if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) {
return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args);
} elseif (null === $this->_mockery_defaultReturnValue) {
return $this->mockery_returnValueForMethod($method);
}
return $this->_mockery_defaultReturnValue;
}
}
$message = 'Method ' . __CLASS__ . '::' . $method .
'() does not exist on this mock object';
if (!is_null($rm)) {
$message = 'Received ' . __CLASS__ .
'::' . $method . '(), but no expectations were specified';
}
$bmce = new BadMethodCallException($message);
$this->_mockery_thrownExceptions[] = $bmce;
throw $bmce;
}
/**
* Uses reflection to get the list of all
* methods within the current mock object
*
* @return array
*/
protected function mockery_getMethods()
{
if (static::$_mockery_methods && \Mockery::getConfiguration()->reflectionCacheEnabled()) {
return static::$_mockery_methods;
}
if (isset($this->_mockery_partial)) {
$reflected = new \ReflectionObject($this->_mockery_partial);
} else {
$reflected = new \ReflectionClass($this);
}
return static::$_mockery_methods = $reflected->getMethods();
}
private function hasMethodOverloadingInParentClass()
{
// if there's __call any name would be callable
return is_callable('parent::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
}
/**
* @return array
*/
private function getNonPublicMethods()
{
return array_map(
function ($method) {
return $method->getName();
},
array_filter($this->mockery_getMethods(), function ($method) {
return !$method->isPublic();
})
);
}
}

View File

@@ -0,0 +1,38 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
use Mockery\LegacyMockInterface;
interface MockInterface extends LegacyMockInterface
{
/**
* @param mixed $something String method name or map of method => return
* @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function allows($something = []);
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\ExpectsHigherOrderMessage
*/
public function expects($something = null);
}

View File

@@ -0,0 +1,56 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class QuickDefinitionsConfiguration
{
private const QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE = 'QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE';
private const QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION = 'QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION';
/**
* Defines what a quick definition should produce.
* Possible options are:
* - self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION: in this case quick
* definitions define a stub.
* - self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE: in this case quick
* definitions define a mock with an 'at least once' expectation.
*
* @var string
*/
protected $_quickDefinitionsApplicationMode = self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION;
/**
* Returns true if quick definitions should setup a stub, returns false when
* quick definitions should setup a mock with 'at least once' expectation.
* When parameter $newValue is specified it sets the configuration with the
* given value.
*/
public function shouldBeCalledAtLeastOnce(?bool $newValue = null): bool
{
if ($newValue !== null) {
$this->_quickDefinitionsApplicationMode = $newValue
? self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE
: self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION;
}
return $this->_quickDefinitionsApplicationMode === self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE;
}
}

View File

@@ -0,0 +1,48 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class ReceivedMethodCalls
{
private $methodCalls = array();
public function push(MethodCall $methodCall)
{
$this->methodCalls[] = $methodCall;
}
public function verify(Expectation $expectation)
{
foreach ($this->methodCalls as $methodCall) {
if ($methodCall->getMethod() !== $expectation->getName()) {
continue;
}
if (!$expectation->matchArgs($methodCall->getArgs())) {
continue;
}
$expectation->verifyCall($methodCall->getArgs());
}
$expectation->verify();
}
}

View File

@@ -0,0 +1,224 @@
<?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) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
/**
* @internal
*/
class Reflector
{
/**
* Determine if the parameter is typed as an array.
*
* @param \ReflectionParameter $param
*
* @return bool
*/
public static function isArray(\ReflectionParameter $param)
{
$type = $param->getType();
return $type instanceof \ReflectionNamedType && $type->getName();
}
/**
* Compute the string representation for the paramater type.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
*/
public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false)
{
if (!$param->hasType()) {
return null;
}
$type = $param->getType();
$declaringClass = $param->getDeclaringClass();
$typeHint = self::typeToString($type, $declaringClass);
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Compute the string representation for the return type.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
*/
public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type)) {
return null;
}
$typeHint = self::typeToString($type, $method->getDeclaringClass());
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Compute the string representation for the simplest return type.
*
* @param \ReflectionParameter $param
*
* @return string|null
*/
public static function getSimplestReturnType(\ReflectionMethod $method)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type) || $type->allowsNull()) {
return null;
}
$typeInformation = self::getTypeInformation($type, $method->getDeclaringClass());
// return the first primitive type hint
foreach ($typeInformation as $info) {
if ($info['isPrimitive']) {
return $info['typeHint'];
}
}
// if no primitive type, return the first type
foreach ($typeInformation as $info) {
return $info['typeHint'];
}
return null;
}
/**
* Get the string representation of the given type.
*
* @param \ReflectionType $type
* @param string $declaringClass
*
* @return string|null
*/
private static function typeToString(\ReflectionType $type, \ReflectionClass $declaringClass)
{
return \implode('|', \array_map(function (array $typeInformation) {
return $typeInformation['typeHint'];
}, self::getTypeInformation($type, $declaringClass)));
}
/**
* Get the string representation of the given type.
*
* @param \ReflectionType $type
* @param \ReflectionClass $declaringClass
*
* @return list<array{typeHint: string, isPrimitive: bool}>
*/
private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass)
{
// PHP 8 union types can be recursively processed
if ($type instanceof \ReflectionUnionType) {
$types = [];
foreach ($type->getTypes() as $innterType) {
foreach (self::getTypeInformation($innterType, $declaringClass) as $info) {
if ($info['typeHint'] === 'null' && $info['isPrimitive']) {
continue;
}
$types[] = $info;
}
}
return $types;
}
// $type must be an instance of \ReflectionNamedType
$typeHint = $type->getName();
// builtins can be returned as is
if ($type->isBuiltin()) {
return [
[
'typeHint' => $typeHint,
'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']),
],
];
}
// 'static' can be returned as is
if ($typeHint === 'static') {
return [
[
'typeHint' => $typeHint,
'isPrimitive' => false,
],
];
}
// 'self' needs to be resolved to the name of the declaring class
if ($typeHint === 'self') {
$typeHint = $declaringClass->getName();
}
// 'parent' needs to be resolved to the name of the parent class
if ($typeHint === 'parent') {
$typeHint = $declaringClass->getParentClass()->getName();
}
// class names need prefixing with a slash
return [
[
'typeHint' => sprintf('\\%s', $typeHint),
'isPrimitive' => false,
],
];
}
/**
* Format the given type as a nullable type.
*
* @param string $typeHint
*
* @return string
*/
private static function formatNullableType($typeHint)
{
if (\PHP_VERSION_ID < 80000) {
return sprintf('?%s', $typeHint);
}
return $typeHint === 'mixed' ? 'mixed' : sprintf('%s|null', $typeHint);
}
}

View File

@@ -0,0 +1,46 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class Undefined
{
/**
* Call capturing to merely return this same object.
*
* @param string $method
* @param array $args
* @return self
*/
public function __call($method, array $args)
{
return $this;
}
/**
* Return a string, avoiding E_RECOVERABLE_ERROR
*
* @return string
*/
public function __toString()
{
return __CLASS__ . ":" . spl_object_hash($this);
}
}

View File

@@ -0,0 +1,107 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class VerificationDirector
{
private $receivedMethodCalls;
private $expectation;
public function __construct(ReceivedMethodCalls $receivedMethodCalls, VerificationExpectation $expectation)
{
$this->receivedMethodCalls = $receivedMethodCalls;
$this->expectation = $expectation;
}
public function verify()
{
return $this->receivedMethodCalls->verify($this->expectation);
}
public function with(...$args)
{
return $this->cloneApplyAndVerify("with", $args);
}
public function withArgs($args)
{
return $this->cloneApplyAndVerify("withArgs", array($args));
}
public function withNoArgs()
{
return $this->cloneApplyAndVerify("withNoArgs", array());
}
public function withAnyArgs()
{
return $this->cloneApplyAndVerify("withAnyArgs", array());
}
public function times($limit = null)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("times", array($limit));
}
public function once()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("once", array());
}
public function twice()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("twice", array());
}
public function atLeast()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array());
}
public function atMost()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array());
}
public function between($minimum, $maximum)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum));
}
protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
{
$expectation = clone $this->expectation;
$expectation->clearCountValidators();
call_user_func_array(array($expectation, $method), $args);
$director = new VerificationDirector($this->receivedMethodCalls, $expectation);
$director->verify();
return $director;
}
protected function cloneApplyAndVerify($method, $args)
{
$expectation = clone $this->expectation;
call_user_func_array(array($expectation, $method), $args);
$director = new VerificationDirector($this->receivedMethodCalls, $expectation);
$director->verify();
return $director;
}
}

View File

@@ -0,0 +1,35 @@
<?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 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class VerificationExpectation extends Expectation
{
public function clearCountValidators()
{
$this->_countValidators = array();
}
public function __clone()
{
parent::__clone();
$this->_actualCount = 0;
}
}

View File

@@ -0,0 +1,65 @@
<?php
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\AnyArgs;
/**
* 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) 2016 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
if (!function_exists("mock")) {
function mock(...$args)
{
return Mockery::mock(...$args);
}
}
if (!function_exists("spy")) {
function spy(...$args)
{
return Mockery::spy(...$args);
}
}
if (!function_exists("namedMock")) {
function namedMock(...$args)
{
return Mockery::namedMock(...$args);
}
}
if (!function_exists("anyArgs")) {
function anyArgs()
{
return new AnyArgs();
}
}
if (!function_exists("andAnyOtherArgs")) {
function andAnyOtherArgs()
{
return new AndAnyOtherArgs();
}
}
if (!function_exists("andAnyOthers")) {
function andAnyOthers()
{
return new AndAnyOtherArgs();
}
}