comments
This commit is contained in:
parent
1e6afd52e5
commit
10f258f2f9
@ -1,12 +1,64 @@
|
|||||||
<?php
|
<?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 {
|
class MockInvocation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the mocked class on which the method was invoked
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $className;
|
protected $className;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the invoked method
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $method;
|
protected $method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed to the method upon invocation
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $args;
|
protected $args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of times this method was invoked
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
protected $count;
|
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) {
|
public function __construct($className, $methodName, array $args, $count) {
|
||||||
$this->className = $className;
|
$this->className = $className;
|
||||||
$this->method = $methodName;
|
$this->method = $methodName;
|
||||||
@ -14,18 +66,54 @@
|
|||||||
$this->count = $count;
|
$this->count = $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the method
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getMethod() {
|
public function getMethod() {
|
||||||
return $this->method;
|
return $this->method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the arguments
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getArgs() {
|
public function getArgs() {
|
||||||
return $this->args;
|
return $this->args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the class
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function getClass() {
|
public function getClass() {
|
||||||
return $this->className;
|
return $this->className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function getCount() {
|
public function getCount() {
|
||||||
return $this->count;
|
return $this->count;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,60 @@
|
|||||||
<?php
|
<?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 {}
|
interface MockObject {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MockObjectCreator
|
||||||
|
*
|
||||||
|
* @package TUnit
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
class MockObjectCreator {
|
class MockObjectCreator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object to mock
|
||||||
|
*
|
||||||
|
* @var ReflectionClass
|
||||||
|
*/
|
||||||
protected $referenceObject;
|
protected $referenceObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The methods to mock
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
protected $methods;
|
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) {
|
public function __construct($class, $callParent = true) {
|
||||||
if (!class_exists($class) && !interface_exists($class)) {
|
if (!class_exists($class) && !interface_exists($class)) {
|
||||||
throw new InvalidArgumentException('The class "' . $class . '" does not exist');
|
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 = '') {
|
public function addMethod($methodName, $callParent = false, $body = '') {
|
||||||
$methodType = 'generic';
|
$methodType = 'generic';
|
||||||
if ($this->referenceObject->hasMethod($methodName)) {
|
if ($this->referenceObject->hasMethod($methodName)) {
|
||||||
@ -58,10 +117,35 @@
|
|||||||
return $this;
|
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();
|
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 = '') {
|
public function generate(array $constructorArgs = array(), $name = '') {
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
$className = $this->referenceObject->getName();
|
$className = $this->referenceObject->getName();
|
||||||
@ -71,7 +155,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (class_exists($name) || interface_exists($name)) {
|
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);
|
$code = $this->generateClassDefinition($name);
|
||||||
@ -84,6 +168,17 @@
|
|||||||
return $obj;
|
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) {
|
protected function generateClassDefinition($name) {
|
||||||
$code = 'class ' . $name . ' ';
|
$code = 'class ' . $name . ' ';
|
||||||
if ($this->referenceObject->isInterface()) {
|
if ($this->referenceObject->isInterface()) {
|
||||||
@ -104,6 +199,18 @@
|
|||||||
return $code;
|
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) {
|
protected function generateMethodDefinition($type, $name, array $methodData) {
|
||||||
$modifier = 'public';
|
$modifier = 'public';
|
||||||
$params = '';
|
$params = '';
|
||||||
|
@ -1,22 +1,85 @@
|
|||||||
<?php
|
<?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 {
|
class MockRegistry {
|
||||||
|
|
||||||
private static $trackers = array();
|
/**
|
||||||
|
* Array of {@link InvocationTracker}s
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $trackers = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of {@link InvocationExpectation}s
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
private static $expectations = array();
|
private static $expectations = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
private function __construct() {}
|
private function __construct() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the registry
|
||||||
|
*
|
||||||
|
* @author Tommy Montgomery
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
public static function reset() {
|
public static function reset() {
|
||||||
self::$trackers = array();
|
self::$trackers = array();
|
||||||
self::$expectations = 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) {
|
public static function addClass($className) {
|
||||||
self::$trackers[$className] = new InvocationTracker();
|
self::$trackers[$className] = new InvocationTracker();
|
||||||
self::$expectations[$className] = array();
|
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) {
|
public static function addExpectation($className, InvocationExpectation $expectation) {
|
||||||
if (!isset(self::$expectations[$className])) {
|
if (!isset(self::$expectations[$className])) {
|
||||||
throw new LogicException('Unable to add invocation expectation because the object does not exist in the registry');
|
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;
|
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() {
|
public static function getAllExpectations() {
|
||||||
return Util::arrayFlatten(self::$expectations);
|
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) {
|
public static function getExpectations($className) {
|
||||||
if (!isset(self::$expectations[$className])) {
|
if (!isset(self::$expectations[$className])) {
|
||||||
throw new LogicException('Unable to add invocation expectation because the object does not exist in the registry');
|
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];
|
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) {
|
public static function registerInvocation($className, $methodName, array $args) {
|
||||||
if (!isset(self::$trackers[$className])) {
|
if (!isset(self::$trackers[$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');
|
||||||
@ -47,6 +146,17 @@
|
|||||||
return $expectation;
|
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) {
|
public static function getTracker($name) {
|
||||||
if (!isset(self::$trackers[$name])) {
|
if (!isset(self::$trackers[$name])) {
|
||||||
throw new LogicException('Unable to retrieve invocation tracker because the object does not exist in the registry');
|
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];
|
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() {
|
public static function getTrackers() {
|
||||||
return self::$trackers;
|
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) {
|
private static function getInvocationCount($className, $methodName) {
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach (self::$trackers[$className]->getInvocations() as $invocation) {
|
foreach (self::$trackers[$className]->getInvocations() as $invocation) {
|
||||||
|
Loading…
Reference in New Issue
Block a user