Last active
December 14, 2015 17:49
-
-
Save maryo/5125089 to your computer and use it in GitHub Desktop.
Simple function mocker for PHP 5.3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class FunctionMocker | |
{ | |
/** @var FunctionMocker[] */ | |
private static $instances = array(); | |
/** @var string */ | |
private $namespace; | |
/** @var string */ | |
private $function; | |
/** @var callable $callback */ | |
private $callback; | |
/** @var int */ | |
private $numberOfCalls = 0; | |
/** | |
* @param string $namespace | |
* @param string $function | |
*/ | |
private function __construct($namespace, $function) | |
{ | |
$this->namespace = (string) $namespace; | |
$this->function = (string) $function; | |
} | |
/** | |
* @param string $namespace | |
* @param string $function | |
* @return FunctionMocker | |
*/ | |
public static function getInstance($namespace, $function) | |
{ | |
$name = sprintf('%s\%s', $namespace, $function); | |
if (!isset(self::$instances[$name])) { | |
self::$instances[$name] = new self($namespace, $function); | |
} | |
return self::$instances[$name]; | |
} | |
/** | |
* @return int | |
*/ | |
public function getNumberOfCalls() | |
{ | |
return $this->numberOfCalls; | |
} | |
public function resetNumberOfCalls() | |
{ | |
$this->numberOfCalls = 0; | |
} | |
/** | |
* @param callable|null $callback | |
* @throws \InvalidArgumentException | |
*/ | |
public function mock($callback = null) | |
{ | |
$this->callback = $callback ?: $this->function; | |
$function = sprintf('\%s\%s', $this->namespace, $this->function); | |
if (!is_callable($this->callback, false, $name)) { | |
throw new \InvalidArgumentException(sprintf('"%s" is not callable', $name)); | |
} | |
if (function_exists($function)) { | |
throw new \RuntimeException(sprintf( | |
'The function "%s" already exists. It can be mocked only once per namespace.', | |
$function | |
)); | |
} | |
eval(sprintf( | |
' | |
namespace %s; | |
function %s() | |
{ | |
$functionMocker = \%s::getInstance(__NAMESPACE__, "%s"); | |
return $functionMocker->call(func_get_args()); | |
} | |
', | |
$this->namespace, | |
$this->function, | |
__CLASS__, | |
$this->function | |
)); | |
} | |
/** | |
* @param array $arguments | |
* @return mixed | |
* {@internal} | |
*/ | |
public function call(array $arguments) | |
{ | |
$this->numberOfCalls++; | |
return call_user_func_array($this->callback, $arguments); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Test; | |
$timeMocker = \FunctionMocker::getInstance(__NAMESPACE__, 'time'); | |
$timeMocker->mock(function() { | |
return '123456'; | |
}); | |
// string(6) "123456" int(1) | |
var_dump(time(), $timeMocker->getNumberOfCalls()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment