more mock object mayhem
This commit is contained in:
		
							parent
							
								
									1cfd39d915
								
							
						
					
					
						commit
						d5134b4ec8
					
				| @ -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); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 			$code  = "	$modifier function $name($params) {\n"; | ||||
| 			$code .= "		MockObject::registerInvocation(get_class($this), __FUNCTION__, func_get_args());\n"; | ||||
| 			 | ||||
| 		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 .= '}'; | ||||
| 			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; | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| @ -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, ', '); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 
 | ||||
| ?>
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user