comments
This commit is contained in:
parent
1e6afd52e5
commit
10f258f2f9
@ -1,12 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MockInvocation
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Struct representing an invocation of mocked method
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
class MockInvocation {
|
||||
|
||||
/**
|
||||
* The name of the mocked class on which the method was invoked
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $className;
|
||||
|
||||
/**
|
||||
* Name of the invoked method
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method;
|
||||
|
||||
/**
|
||||
* The arguments passed to the method upon invocation
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $args;
|
||||
|
||||
/**
|
||||
* The number of times this method was invoked
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
* @param array $args
|
||||
* @param int $count
|
||||
*/
|
||||
public function __construct($className, $methodName, array $args, $count) {
|
||||
$this->className = $className;
|
||||
$this->method = $methodName;
|
||||
@ -14,18 +66,54 @@
|
||||
$this->count = $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the method
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod() {
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arguments
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArgs() {
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the class
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getClass() {
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the count
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCount() {
|
||||
return $this->count;
|
||||
}
|
||||
|
@ -1,15 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File containing MockObject, MockObjectCreator
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* MockObject dummy interface
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
interface MockObject {}
|
||||
|
||||
/**
|
||||
* Class MockObjectCreator
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
class MockObjectCreator {
|
||||
|
||||
/**
|
||||
* The object to mock
|
||||
*
|
||||
* @var ReflectionClass
|
||||
*/
|
||||
protected $referenceObject;
|
||||
|
||||
/**
|
||||
* The methods to mock
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $methods;
|
||||
|
||||
protected static $registry = array();
|
||||
protected static $expectations = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $class The name of the class or interface to mock
|
||||
* @param bool $callParent Whether to call the parent constructor
|
||||
* @throws InvalidArgumentException
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function __construct($class, $callParent = true) {
|
||||
if (!class_exists($class) && !interface_exists($class)) {
|
||||
throw new InvalidArgumentException('The class "' . $class . '" does not exist');
|
||||
@ -33,6 +78,20 @@
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a method to mock
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses methodIsMockable()
|
||||
*
|
||||
* @param string $methodName Name of the method to mock
|
||||
* @param bool $callParent Whether to call the parent
|
||||
* @param string $body Custom PHP code to execute in the method body
|
||||
* @throws LogicException if the method is not mockable
|
||||
* @return MockObjectCreator
|
||||
*/
|
||||
public function addMethod($methodName, $callParent = false, $body = '') {
|
||||
$methodType = 'generic';
|
||||
if ($this->referenceObject->hasMethod($methodName)) {
|
||||
@ -58,10 +117,35 @@
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function methodIsMockable(ReflectionMethod $method) {
|
||||
/**
|
||||
* Determines if a method is mockable
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param ReflectionMethod $method
|
||||
* @return bool
|
||||
*/
|
||||
protected final function methodIsMockable(ReflectionMethod $method) {
|
||||
return !$method->isFinal() && !$method->isPrivate() && !$method->isStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the mock object
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses generateClassDefinition()
|
||||
* @uses MockRegistry::addClass()
|
||||
*
|
||||
* @param array $constructorArgs Arguments to pass to the constructor
|
||||
* @param string $name Custom name to give the newly created mock object, by default
|
||||
* a random, unused name is chosen
|
||||
* @throws LogicException if a name is given that is already in use
|
||||
* @return object
|
||||
*/
|
||||
public function generate(array $constructorArgs = array(), $name = '') {
|
||||
if (empty($name)) {
|
||||
$className = $this->referenceObject->getName();
|
||||
@ -71,7 +155,7 @@
|
||||
}
|
||||
|
||||
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');
|
||||
throw new LogicException('Cannot use the name "' . $name . '" for mock object because the class or interface already exists');
|
||||
}
|
||||
|
||||
$code = $this->generateClassDefinition($name);
|
||||
@ -84,6 +168,17 @@
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the class definition of the mock object
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses generateMethodDefinition()
|
||||
*
|
||||
* @param string $name The name of the class
|
||||
* @return string Executable PHP code that will generate a class when eval()'d
|
||||
*/
|
||||
protected function generateClassDefinition($name) {
|
||||
$code = 'class ' . $name . ' ';
|
||||
if ($this->referenceObject->isInterface()) {
|
||||
@ -104,6 +199,18 @@
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a method definition
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $type "default" or "generic"
|
||||
* @param string $name Name of the method
|
||||
* @param array $methodData Should have keys "call_parent" and "body"
|
||||
* @return string
|
||||
*/
|
||||
protected function generateMethodDefinition($type, $name, array $methodData) {
|
||||
$modifier = 'public';
|
||||
$params = '';
|
||||
|
@ -1,22 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MockRegistry
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Registry of mock objects
|
||||
*
|
||||
* @package TUnit
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
class MockRegistry {
|
||||
|
||||
/**
|
||||
* Array of {@link InvocationTracker}s
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $trackers = array();
|
||||
|
||||
/**
|
||||
* Array of {@link InvocationExpectation}s
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $expectations = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @ignore
|
||||
*/
|
||||
private function __construct() {}
|
||||
|
||||
/**
|
||||
* Resets the registry
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function reset() {
|
||||
self::$trackers = array();
|
||||
self::$expectations = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a class to the registry and registers a tracker for it
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $className
|
||||
*/
|
||||
public static function addClass($className) {
|
||||
self::$trackers[$className] = new InvocationTracker();
|
||||
self::$expectations[$className] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an expectation for the specified class
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $className
|
||||
* @param InvocationExpectation $expectation
|
||||
* @throws LogicException if the class does not exist in the registry
|
||||
*/
|
||||
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');
|
||||
@ -25,10 +88,31 @@
|
||||
self::$expectations[$className][] = $expectation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all registered expectations
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses Util::arrayFlatten()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllExpectations() {
|
||||
return Util::arrayFlatten(self::$expectations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all registered expectations for the specified class
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $className
|
||||
* @throws LogicException if the class does not exist in the registry
|
||||
* @return array
|
||||
*/
|
||||
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');
|
||||
@ -37,6 +121,21 @@
|
||||
return self::$expectations[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an invocation for the specified class
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses getInvocationCount()
|
||||
* @uses InvocationTracker::registerInvocation()
|
||||
*
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
* @param array $args
|
||||
* @throws LogicException if the class does not exist in the registry
|
||||
* @return InvocationExpectation|false Returns the matched invocation, or false if no match
|
||||
*/
|
||||
public static function registerInvocation($className, $methodName, array $args) {
|
||||
if (!isset(self::$trackers[$className])) {
|
||||
throw new LogicException('Unable to register invocation because the object does not exist in the registry');
|
||||
@ -47,6 +146,17 @@
|
||||
return $expectation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tracker for the specified class
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @param string $name
|
||||
* @throws LogicException if the class does not exist in the registry
|
||||
* @return InvocationTracker
|
||||
*/
|
||||
public static function getTracker($name) {
|
||||
if (!isset(self::$trackers[$name])) {
|
||||
throw new LogicException('Unable to retrieve invocation tracker because the object does not exist in the registry');
|
||||
@ -55,10 +165,32 @@
|
||||
return self::$trackers[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all registered {@link InvocationTracker}s
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTrackers() {
|
||||
return self::$trackers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current invocation count for the class and method
|
||||
*
|
||||
* @author Tommy Montgomery
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @uses InvocationTracker::getInvocations()
|
||||
* @uses MockInvocation::getMethod()
|
||||
*
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
* @return int
|
||||
*/
|
||||
private static function getInvocationCount($className, $methodName) {
|
||||
$count = 0;
|
||||
foreach (self::$trackers[$className]->getInvocations() as $invocation) {
|
||||
|
Loading…
Reference in New Issue
Block a user