znt/test/lib/test.class.php

210 lines
7.7 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types = 1);
/**
* ZenTaoPHP 的测试基类,通过反射实现对被测试类的调用。
* The test base class of ZenTaoPHP, which implements the call to the class being tested through reflection.
*
* 测试基类的子类可以通过继承 baseTest 类来实现对被测试类的测试。
* The subclass of the test base class can implement the test of the class being tested by inheriting the baseTest class.
*
* 测试基类的子类需要定义受保护的属性 moduleName className 来指定被测试的模块名和类名。
* The subclass of the test base class needs to define the protected properties moduleName and className to specify the module name and class name being tested.
*
* 测试基类的子类可以通过调用 getProperty 方法来获取被测试类的属性值。
* The subclass of the test base class can call the getProperty method to get the property value of the class being tested.
*
* 测试基类的子类可以通过调用 invokeArgs 方法来调用被测试类的方法。
* The subclass of the test base class can call the invokeArgs method to invoke the method of the class being tested.
*
* 例如:
* For example:
*
* class userZenTest extends baseTest
* {
* protected $moduleName = 'user';
* protected $className = 'zen';
*
* public function prepareCustomFieldsTest($method = 'batchCreate', $requiredMethod = 'create')
* {
* $this->invokeArgs('prepareCustomFields', [$method, $requiredMethod]);
* if(dao::isError()) return dao::getError();
*
* return $this->getProperty('view');
* }
* }
*
*/
class baseTest
{
/**
* 被测试的模块名。
* The name of the module being tested.
*
* @var string
* @access private
*/
protected $moduleName = '';
/**
* 被测试的类名zen、tao model。
* The class name being tested, zen, tao or model.
*
* @var string
* @access private
*/
protected $className = '';
/**
* 被测试的类的实例。
* The instance of the class being tested.
*
* @var object
* @access private
*/
public $instance = null;
/**
* 被测试的类的反射对象。
* The reflection object of the class being tested.
*
* @var ReflectionClass
* @access private
*/
protected $reflection = null;
/**
* 缓存被测试类的实例。
* Cache the instances of the classes being tested.
*
* @var array
* @access private
*/
protected static $instances = [];
/**
* 缓存被测试类的反射对象。
* Cache the reflection objects of the classes being tested.
*
* @var array
* @access private
*/
protected static $reflections = [];
/**
* 构造函数,初始化被测试的类的实例和反射对象。
* Constructor, initialize the instance and reflection object of the class being tested.
*
* @access public
* @return void
*/
public function __construct($moduleName = '', $className = '')
{
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($className)) $className = $this->className;
if(empty($moduleName) || empty($className))
{
throw new InvalidArgumentException('Module name and class name cannot be empty.');
}
global $app;
$app->setModuleName($moduleName);
$this->instance = $this->getInstance($moduleName, $className);
$this->reflection = $this->getReflection($moduleName, $className);
}
/**
* 获取被测试的类的实例。
* Get the instance of the class being tested.
*
* @param string $moduleName 模块名 The module name
* @param string $className 类名 The class name
* @access protected
* @return object
*/
protected function getInstance($moduleName, $className)
{
if(isset(self::$instances[$className][$moduleName])) return self::$instances[$className][$moduleName];
global $app;
if($className == 'zen') require_once $app->getModulePath('', $moduleName) . 'control.php';
if($className == 'tao') require_once $app->getModulePath('', $moduleName) . 'model.php';
self::$instances[$className][$moduleName] = $app->loadTarget($moduleName, '', $className);
return self::$instances[$className][$moduleName];
}
/**
* 获取被测试的类的反射对象。
* Get the reflection object of the class being tested.
*
* @param string $moduleName 模块名 The module name
* @param string $className 类名 The class name
* @param object|null $instance 类的实例 The instance of the class
* @access protected
* @return ReflectionClass
*/
protected function getReflection($moduleName, $className, $instance = null)
{
if(isset(self::$reflections[$className][$moduleName])) return self::$reflections[$className][$moduleName];
if(empty($instance)) $instance = $this->getInstance($moduleName, $className);
self::$reflections[$className][$moduleName] = new ReflectionClass($instance);
return self::$reflections[$className][$moduleName];
}
/**
* 获取被测试类的属性值。
* Get the property value of the class being tested.
*
* @param string $propertyName 属性名 The property name
* @param string $moduleName 模块名 The module name
* @param string $className 类名 The class name
* @param object|null $instance 类的实例 The instance of the class
* @param ReflectionClass|null $reflection 类的反射对象 The reflection object of the class
* @access protected
* @return mixed
*/
protected function getProperty($propertyName, $moduleName = '', $className = '', $instance = null, $reflection = null)
{
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($className)) $className = $this->className;
if(empty($instance)) $instance = $this->getInstance($moduleName, $className);
if(empty($reflection)) $reflection = $this->getReflection($moduleName, $className, $instance);
$property = $reflection->getProperty($propertyName);
if(!$property->isPublic()) $property->setAccessible(true);
return $property->getValue($instance);
}
/**
* 调用被测试类的方法。
* Invoke the method of the class being tested.
*
* @param string $methodName 方法名 The method name
* @param array $args 方法参数 The method arguments
* @param string $moduleName 模块名 The module name
* @param string $className 类名 The class name
* @param object|null $instance 类的实例 The instance of the class
* @param ReflectionClass|null $reflection 类的反射对象 The reflection object of the class
* @access protected
* @return mixed
*/
protected function invokeArgs($methodName, $args = [], $moduleName = '', $className = '', $instance = null, $reflection = null)
{
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($className)) $className = $this->className;
if(empty($instance)) $instance = $this->getInstance($moduleName, $className);
if(empty($reflection)) $reflection = $this->getReflection($moduleName, $className, $instance);
$method = $reflection->getMethod($methodName);
if(!$method->isPublic()) $method->setAccessible(true);
$object = $method->isStatic() ? null : $instance;
return $method->invokeArgs($object, $args);
}
}