[英]SUT parent checks dependencies with get_class
它始于我到处执行null检查以确保我的交互器具有必要的实体时开始。 幸运的是,我碰到了这篇文章,指出不允许实体处于无效状态,请在构造函数中进行检查 。 现在,我的交互器使用protected static $request
来明确声明它们需要哪些实体,然后在实例化期间将其传递。 我选择了static,因此可以在创建Interactor实例之前进行检查。
abstract class Interactor {
protected static $request = [];
protected $entities = [];
final public function __construct(Entity ...$entities) {
$this->setEntities(...$entities);
$this->checkEntities();
}
final private function setEntities(Entity ...$entities) {
foreach($entities as $entity) {
$this->setEntity($entity);
}
}
final private function setEntity(Entity $entity){
$className = get_class($entity);
if (!in_array($className, static::$request)){
throw new Exception("Not a requested entity");
}
$this->entities[$className] = $entity;
}
final private function checkEntities(){
if (count(static::$request) != count($this->entities))
throw new Exception("Entity mismatch");
foreach(static::$request as $index=>$name) {
if (!array_key_exists($name, $this->entities))
throw new Exception("Missing requested entity ($name)");
if (!is_a($this->entities[$name], $name))
throw new Exception("Not the specified entity");
}
}
final public static function getRequest(){
return array_values(static::$request);
}
}
好的,很好,现在我只在一个位置进行检查,而不必担心在函数开始时执行空检查。 我现在所要解决的问题是我的Interactor正在对照静态类名请求数组检查类名。 因此,当我在测试过程中对模拟实体进行DI时,我的父Interactor会抛出一个异常,指出它不在预先批准的列表中。
下面是简化的Chess示例,以进行演示:
class Chess extends Interactor {
protected static $request = ['Piece','Engine','Board'];
}
然后我们有我们的实体:
abstract class Entity {}
class Piece extends Entity {}
class Engine extends Entity {}
class Board extends Entity {}
最后是我们的测试:
class ChessTest extends TestCase {
function setUp(){
$this->piece = $this->getMockBuilder(Piece::class)->getMock();
$this->engine = $this->getMockBuilder(Engine::class)->getMock();
$this->board = $this->getMockBuilder(Board::class)->getMock();
$this->chess = new Chess($this->piece, $this->engine, $this->board);
}
function testCanSetup(){
$this->assertTrue(
is_a($this->chess, Chess::class)
);
}
}
引发异常:不请求交互器接收实体(Mock_Piece_faaf8b14)
当然Mock_Piece_faaf8b14不会出现在我们的static::$request
数组中,因此注定会引发异常。
到目前为止,我想出的解决方法是包括在Entity中:
public function getClassName(){
return get_called_class();
}
然后在Interactor->setEntity($entity)
而不是使用get_class($entity)
我将使用$entity->getClassName()
,这对于模拟来说很简单。
我认为我创建Interactor的方式与前面提到的内容是一致的,只采用了构造函数中的实体。 但是,当我注入模拟实体时,一切都感到与众不同。
1)有没有办法避免我的实体中出现getClassName()
?
2)我可以模拟的实体中是否有某些东西可以代替而在get_class()
调用?
谢谢您的帮助!
您正在检查类的名称是否是$request
数组中的键之一。 事实并非如此。 数组中的键是数字0、1、2,因此会引发异常。 我认为您想使用in_array
代替。
尽管与此同时,该模拟仍然不会通过,因为您正在检查类名是否在$request
。 因此,该名称也将根本不存在,并且仍然会引发异常。
如果您的Interactor
类所做的全部工作是确保将正确的对象传递到构造函数中,为什么不只使用PHP的本机类型提示呢?
您的Chess
班级变为:
class Chess {
public function __construct(Piece $piece, Engine $engine, Board $board) { }
}
PHP将确保传入的对象具有正确的类型,并允许您模拟它们以进行测试。
您无需完全使用getClassName()
即可进行所需的类型检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.