MOCK OBJECTS FOR LIFE
This commit is contained in:
parent
67a34c7b8f
commit
16533b01d7
97
src/TUnit/framework/mock/InvocationExpectation.php
Normal file
97
src/TUnit/framework/mock/InvocationExpectation.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class InvocationExpectation {
|
||||||
|
|
||||||
|
protected $className;
|
||||||
|
protected $method;
|
||||||
|
protected $count;
|
||||||
|
protected $args;
|
||||||
|
protected $returnValue;
|
||||||
|
protected $echoString;
|
||||||
|
|
||||||
|
public function __construct($methodName) {
|
||||||
|
$this->method = $methodName;
|
||||||
|
$this->count = 0;
|
||||||
|
$this->args = array();
|
||||||
|
$this->returnValue = null;
|
||||||
|
$this->echoString = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function getMethod() {
|
||||||
|
return $this->method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function getCount() {
|
||||||
|
return $this->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function getArgs() {
|
||||||
|
return $this->args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toBeCalled($count) {
|
||||||
|
$this->count = $count;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toBeCallExactly($count) {
|
||||||
|
throw new BadMethodCallException('Not implemented yet');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withArguments() {
|
||||||
|
$this->args = func_get_args();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toEcho($value) {
|
||||||
|
if (!is_scalar($value)) {
|
||||||
|
if (is_object($value)) {
|
||||||
|
$refClass = new ReflectionClass($value);
|
||||||
|
if ($refClass->hasMethod('__toString')) {
|
||||||
|
$value = $refClass->getMethod('__toString')->invoke($value);
|
||||||
|
} else {
|
||||||
|
throw new InvalidArgumentException('1st argument must be a scalar value or a __toString()-able object');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvalidArgumentException('1st argument must be a scalar value or a __toString()-able object');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->echoString = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toReturn($value) {
|
||||||
|
$this->returnValue = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function andReturn($value) {
|
||||||
|
$this->toReturn($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
if (!empty($this->echoString)) {
|
||||||
|
echo $this->echoString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function matchesInvocation(MockInvocation $invocation) {
|
||||||
|
return $this->method === $invocation->getMethod() && $this->countIsAcceptable($invocation->getCount()) && $this->args == $invocation->getArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function countIsAcceptable($count) {
|
||||||
|
switch ($count) {
|
||||||
|
case TestCase::ANY:
|
||||||
|
return true;
|
||||||
|
case TestCase::AT_LEAST_ONCE:
|
||||||
|
return $count > 0;
|
||||||
|
default:
|
||||||
|
return $count === $this->count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -10,6 +10,18 @@
|
|||||||
|
|
||||||
public function registerInvocation(MockInvocation $invocation) {
|
public function registerInvocation(MockInvocation $invocation) {
|
||||||
$this->invocations[] = $invocation;
|
$this->invocations[] = $invocation;
|
||||||
|
|
||||||
|
foreach (MockObjectCreator::getExpectations($invocation->getClass()) as $expectation) {
|
||||||
|
if ($expectation->matchesInvocation($invocation)) {
|
||||||
|
return $expectation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvocations() {
|
||||||
|
return $this->invocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
19
src/TUnit/framework/mock/MockHandler.php
Normal file
19
src/TUnit/framework/mock/MockHandler.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class MockHandler {
|
||||||
|
|
||||||
|
private $className;
|
||||||
|
|
||||||
|
public function __construct($mock) {
|
||||||
|
$this->className = get_class($mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expectsMethod($methodName) {
|
||||||
|
$expectation = new InvocationExpectation($methodName);
|
||||||
|
MockObjectCreator::addExpectation($this->className, $expectation);
|
||||||
|
return $expectation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
class MockInvocation {
|
class MockInvocation {
|
||||||
|
|
||||||
|
protected $className;
|
||||||
protected $method;
|
protected $method;
|
||||||
protected $args;
|
protected $args;
|
||||||
|
protected $count;
|
||||||
|
|
||||||
public function __construct($methodName, array $args) {
|
public function __construct($className, $methodName, array $args, $count) {
|
||||||
|
$this->className = $className;
|
||||||
$this->method = $methodName;
|
$this->method = $methodName;
|
||||||
$this->args = $args;
|
$this->args = $args;
|
||||||
|
$this->count = $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMethod() {
|
public function getMethod() {
|
||||||
@ -18,6 +22,14 @@
|
|||||||
return $this->args;
|
return $this->args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getClass() {
|
||||||
|
return $this->className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCount() {
|
||||||
|
return $this->count;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -8,6 +8,7 @@
|
|||||||
protected $methods;
|
protected $methods;
|
||||||
|
|
||||||
protected static $registry = array();
|
protected static $registry = array();
|
||||||
|
protected static $expectations = array();
|
||||||
|
|
||||||
public function __construct($class, $callParent = true) {
|
public function __construct($class, $callParent = true) {
|
||||||
if (!class_exists($class) && !interface_exists($class)) {
|
if (!class_exists($class) && !interface_exists($class)) {
|
||||||
@ -32,12 +33,35 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function resetTrackers() {
|
||||||
|
self::$registry = array();
|
||||||
|
self::$expectations = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addExpectation($className, InvocationExpectation $expectation) {
|
||||||
|
if (!isset(self::$expectations[$className])) {
|
||||||
|
throw new LogicException('Unable to add invocation expectation because the object does not exist in the registry');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$expectations[$className][] = $expectation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getExpectations($className) {
|
||||||
|
if (!isset(self::$expectations[$className])) {
|
||||||
|
throw new LogicException('Unable to add invocation expectation because the object does not exist in the registry');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$expectations[$className];
|
||||||
|
}
|
||||||
|
|
||||||
public static function registerInvocation($className, $methodName, array $args) {
|
public static function registerInvocation($className, $methodName, array $args) {
|
||||||
if (!isset(self::$registry[$className])) {
|
if (!isset(self::$registry[$className])) {
|
||||||
throw new LogicException('Unable to register invocation because the object does not exist in the registry');
|
throw new LogicException('Unable to register invocation because the object does not exist in the registry');
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$registry[$className]->registerInvocation(new MockInvocation($methodName, $args));
|
$count = self::getInvocationCount($className, $methodName);
|
||||||
|
$expectation = self::$registry[$className]->registerInvocation(new MockInvocation($className, $methodName, $args, $count));
|
||||||
|
return $expectation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTracker($name) {
|
public static function getTracker($name) {
|
||||||
@ -48,6 +72,17 @@
|
|||||||
return self::$registry[$name];
|
return self::$registry[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getInvocationCount($className, $methodName) {
|
||||||
|
$count = 1;
|
||||||
|
foreach (self::$registry[$className]->getInvocations() as $invocation) {
|
||||||
|
if ($invocation->getMethod() === $methodName) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
|
||||||
public function addMethod($methodName, $callParent = false, $body = '') {
|
public function addMethod($methodName, $callParent = false, $body = '') {
|
||||||
$methodType = 'generic';
|
$methodType = 'generic';
|
||||||
if ($this->referenceObject->hasMethod($methodName)) {
|
if ($this->referenceObject->hasMethod($methodName)) {
|
||||||
@ -91,8 +126,10 @@
|
|||||||
|
|
||||||
$code = $this->generateClassDefinition($name);
|
$code = $this->generateClassDefinition($name);
|
||||||
eval($code);
|
eval($code);
|
||||||
|
//print_r($code); exit;
|
||||||
|
|
||||||
self::$registry[$name] = new InvocationTracker();
|
self::$registry[$name] = new InvocationTracker();
|
||||||
|
self::$expectations[$name] = array();
|
||||||
|
|
||||||
$obj = new ReflectionClass($name);
|
$obj = new ReflectionClass($name);
|
||||||
$obj = $obj->newInstanceArgs($constructorArgs);
|
$obj = $obj->newInstanceArgs($constructorArgs);
|
||||||
@ -130,21 +167,29 @@
|
|||||||
$paramList = Util::buildParameterNameList($method);
|
$paramList = Util::buildParameterNameList($method);
|
||||||
}
|
}
|
||||||
|
|
||||||
$varName = '$___args_' . uniqid();
|
$temp1 = '$___temp1_' . uniqid();
|
||||||
|
$temp2 = '$___temp2_' . uniqid();
|
||||||
|
$parentCall = ($methodData['call_parent']) ? "parent::$name($paramList);" : '//placeholder for call to parent';
|
||||||
|
$body = (!empty($methodData['body'])) ? str_replace("\n", "\n\t\t", $methodData['body']) : '//placeholder for custom method body';
|
||||||
|
$code = <<<CODE
|
||||||
|
$modifier function $name($params) {
|
||||||
|
$temp1 = func_get_args();
|
||||||
|
$temp2 = MockObjectCreator::registerInvocation(get_class(\$this), __FUNCTION__, $temp1);
|
||||||
|
if ($temp2 instanceof InvocationExpectation) {
|
||||||
|
//this invocation matched an invocation expectation
|
||||||
|
|
||||||
$code = " $modifier function $name($params) {\n";
|
$parentCall
|
||||||
$code .= " $varName = func_get_args();\n";
|
|
||||||
$code .= " MockObjectCreator::registerInvocation(get_class(\$this), __FUNCTION__, $varName);\n";
|
|
||||||
$code .= " unset($varName);\n";
|
|
||||||
|
|
||||||
if ($methodData['call_parent']) {
|
return {$temp2}->execute();
|
||||||
$code .= " parent::$name($paramList);\n";
|
|
||||||
}
|
|
||||||
if (!empty($methodData['body'])) {
|
|
||||||
$code .= "\t\t" . str_replace("\n", "\n\t\t", $methodData['body']) . "\n";
|
|
||||||
}
|
}
|
||||||
|
unset($temp1, $temp2);
|
||||||
|
|
||||||
|
$parentCall
|
||||||
|
|
||||||
|
$body
|
||||||
|
}
|
||||||
|
CODE;
|
||||||
|
|
||||||
$code .= " }";
|
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
|
const ANY = -1;
|
||||||
|
const AT_LEAST_ONCE = -2;
|
||||||
|
|
||||||
|
protected static $mockStorage = array();
|
||||||
|
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
@ -60,6 +65,10 @@
|
|||||||
return $creator->generate($args, $name);
|
return $creator->generate($args, $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function mock(MockObject $mock) {
|
||||||
|
return new MockHandler($mock);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Autoload manifest
|
* Autoload manifest
|
||||||
*
|
*
|
||||||
* Autogenerated by manifester.php on 2009-06-15 20:40:53
|
* Autogenerated by manifester.php on 2009-06-16 22:58:05
|
||||||
*
|
*
|
||||||
* @package TUnit
|
* @package TUnit
|
||||||
* @version 0.1.0
|
* @version 0.1.0
|
||||||
@ -30,8 +30,10 @@
|
|||||||
'IdenticalConstraint' => 'TUnit/framework/constraints/IdenticalConstraint.php',
|
'IdenticalConstraint' => 'TUnit/framework/constraints/IdenticalConstraint.php',
|
||||||
'IgnoredTest' => 'TUnit/framework/result/FailedTest.php',
|
'IgnoredTest' => 'TUnit/framework/result/FailedTest.php',
|
||||||
'IgnoredTestResult' => 'TUnit/framework/result/IgnoredTestResult.php',
|
'IgnoredTestResult' => 'TUnit/framework/result/IgnoredTestResult.php',
|
||||||
|
'InvocationExpectation' => 'TUnit/framework/mock/InvocationExpectation.php',
|
||||||
'InvocationTracker' => 'TUnit/framework/mock/InvocationTracker.php',
|
'InvocationTracker' => 'TUnit/framework/mock/InvocationTracker.php',
|
||||||
'IssetConstraint' => 'TUnit/framework/constraints/SimpleConstraints.php',
|
'IssetConstraint' => 'TUnit/framework/constraints/SimpleConstraints.php',
|
||||||
|
'MockHandler' => 'TUnit/framework/mock/MockHandler.php',
|
||||||
'MockInvocation' => 'TUnit/framework/mock/MockInvocation.php',
|
'MockInvocation' => 'TUnit/framework/mock/MockInvocation.php',
|
||||||
'MockObject' => 'TUnit/framework/mock/MockObject.php',
|
'MockObject' => 'TUnit/framework/mock/MockObject.php',
|
||||||
'MockObjectCreator' => 'TUnit/framework/mock/MockObject.php',
|
'MockObjectCreator' => 'TUnit/framework/mock/MockObject.php',
|
||||||
|
Loading…
Reference in New Issue
Block a user