more mock object mayhem

This commit is contained in:
tmont 2009-06-15 09:22:37 +00:00
parent 1cfd39d915
commit d5134b4ec8
2 changed files with 113 additions and 25 deletions

View File

@ -7,6 +7,8 @@
protected $referenceObject;
protected $methods;
protected static $registry = array();
public function __construct($class) {
if (!class_exists($class) || !interface_exists($class)) {
throw new InvalidArgumentException('The class "' . $class . '" does not exist');
@ -19,12 +21,33 @@
}
$this->referenceObject = $refClass;
$this->methods = array(
'default' => array(),
$this->methods = array(
'default' => array(
$this->referenceObject->getConstructor()->getName() => array(
'body' => '',
'call_parent' => true
)
),
'generic' => array()
);
}
public static function registerInvocation($name, MockInvocation $invocation) {
if (!isset(self::$registry[$name])) {
throw new LogicException('Unable to register invocation because the object does not exist in the registry');
}
self::$registry[$name]->registerInvocation($invocation);
}
public static function getTracker($name) {
if (!isset(self::$registry[$name])) {
throw new LogicException('Unable to retrieve invocation tracker because the object does not exist in the registry');
}
return self::$registry[$name];
}
public function addMethod($methodName, $callParent = false, $body = '') {
$methodType = 'generic';
@ -55,10 +78,6 @@
return !$method->isFinal() && !$method->isPrivate() && !$method->isStatic();
}
protected function getDefaultMethodBody() {
}
public function generate(array $constructorArgs = array(), $name = '') {
if (empty($name)) {
$className = $this->referenceObject->getName();
@ -70,15 +89,29 @@
if (class_exists($name) || interface_exists($name)) {
throw new RuntimeException('Cannot use the name "' . $name . '" for mock object because the class or interface already exists');
}
$code = $this->generateClassDefinition($name);
eval($code);
$obj = new ReflectionClass($name);
$obj = $obj->newInstanceArgs($constructorArgs);
self::$registry[$name] = new InvocationTracker();
return $obj;
}
private function generateClassDefinition(ReflectionClass $class, array $methods, array $args, $name) {
$code = 'class ' . $name . ' ' . ($class->isInterface() ? 'implements' : 'extends') . $class->getName() . ' {' . "\n";
protected function generateClassDefinition($name) {
$code = 'class ' . $name . ' ';
if ($this->referenceObject->isInterface()) {
$code .= 'implements ' . $this->referenceObject->getName() . ', MockObject';
} else {
$code .= 'extends ' . $this->getReferenceObject->getName() . ' implements MockObject';
}
$genericMethods = array();
foreach ($methods as $method) {
if ($class->hasMethod($method)) {
$code .= self::generateMethodDefinition($class->getMethod($method));
$code .= " {\n";
foreach ($this->methods as $type => $methods) {
foreach ($methods as $method => $methodData) {
$code .= $this->generateMethodDefinition($type, $method, $methodData);
}
}
@ -86,20 +119,28 @@
return $code;
}
private function generateMethodDefinition(ReflectionMethod $method) {
protected function generateMethodDefinition($type, $name, array $methodData) {
$modifier = 'public';
$params = '';
$paramList = '';
if ($type === 'default') {
$method = $this->referenceObject->getMethod($name);
$modifier = ($method->isPublic()) ? 'public' : 'protected';
$params = Util::buildParameterList($method);
$paramList = Util::getParameterNameList($method);
}
}
private function generateGenericMethodDefinition(array $methods) {
$code = 'public function __call($method, array $args) {' . "\n";
$code .= ' $allowedMethods = ' . var_export($methods, true) . ';' . "\n";
$code .= ' if (in_array($method, $allowedMethods)) {' . "\n";
$code .= ' ' . "\n";
$code .= ' } else {' . "\n";
$code .= ' throw new BadMethodCallException(\'The method "\' . $method . \'" does not exist on the mocked class "\' . get_class($this) . \'"\');' . "\n";
$code .= ' }' . "\n";
$code .= '}';
$code = " $modifier function $name($params) {\n";
$code .= " MockObject::registerInvocation(get_class($this), __FUNCTION__, func_get_args());\n";
if ($methodData['call_parent']) {
$code .= " parent::$name($paramList);\n";
}
if (!empty($methodData['body'])) {
$code .= "\t\t" . str_replace("\n", "\n\t\t", $methodData['body']) . "\n";
}
$code .= ' }';
return $code;
}

View File

@ -22,10 +22,57 @@
case 'resource':
return 'resource of type ' . get_resource_type($var);
case 'array':
return 'array(' . count($var) . ')';
return 'array[' . count($var) . ']';
}
}
public static function buildParameterDefinition(ReflectionMethod $method) {
$paramList = '';
foreach ($method->getParameters() as $i => $param) {
if ($param->getClass()) {
$paramList .= $param->getClass() . ' ';
} else if ($param->isArray()) {
$paramList .= 'array ';
}
if ($param->isPassedByReference()) {
$paramList .= '&';
}
$paramList .= self::repairParameterName($param->getName(), $i);
if ($param->isOptional()) {
$paramList .= ' = ';
if ($param->isDefaultValueAvailable()) {
$paramList .= var_export($param->getDefaultValue(), true);
} else {
$paramList .= 'null';
}
}
$paramList .= ',';
}
return rtrim($paramList, ', ');
}
private static repairParameterName($name, $position) {
if (empty($name)) {
$name = 'param' . $position;
}
return $name;
}
public static function buildParameterNameList(ReflectionMethod $method) {
$list = '';
foreach ($method->getParameters() as $param) {
$list .= '$' . self::repairParamterName($param->getName()) . ', ';
}
return rtrim($list, ', ');
}
}
?>