我刚刚开始使用PHPSpec,我真的很喜欢在PHPUnit上使用它,尤其是无需任何努力的mock和stub。无论如何,我尝试测试的方法需要一个Cell
对象数组。我如何告诉PHPSpec给我一系列模拟?
我的班级的简化版本
<?php
namespace Mything;
class Row
{
/** @var Cell[] */
protected $cells;
/**
* @param Cell[] $cells
*/
public function __construct(array $cells)
{
$this->setCells($cells);
}
/**
* @param Cell[] $cells
* @return Row
*/
public function setCells(array $cells)
{
// validate that $cells only contains instances of Cell
$this->cells = $cells;
return $this;
}
}
我的测试的简化版本
<?php
namespace specMyThingRow;
use MyThingCell;
use PhpSpecObjectBehavior;
class RowSpec extends ObjectBehavior
{
function let()
{
// need to get an array of Cell objects
$this->beConstructedWith($cells);
}
function it_is_initializable()
{
$this->shouldHaveType('MyThingRow');
}
// ...
}
我本来希望我能做以下操作,但它后来抱怨找不到Cell[]
。使用FQN,它抱怨找不到MyThingCell[]
。
/**
* @param Cell[] $cells
*/
function let($cells)
{
// need to get an array of Cell objects
$this->beConstructedWith($cells);
}
我唯一能想到的选项是传递多个类型提示的Cell
参数,并手动将它们组合成一个数组。我是不是错过了一些简单的东西?
编辑:我使用的是PHPSpec2.5.3,不幸的是,服务器目前被困在PHP 5.3:-(
你为什么不做一些类似的事情
use ProphecyProphet;
use Cell; // adapt it with PSR-4 and make it use correct class
class RowSpec extends ObjectBehavior
{
private $prophet;
private $cells = [];
function let()
{
$this->prophet = new Prophet();
for ($i = 0; $i < 10; $i++) {
$this->cells[] = $this->prophet->prophesize(Cell::class);
}
$this->beConstructedWith($cells);
}
// ....
function letGo()
{
$this->prophet->checkPredictions();
}
public function it_is_a_dummy_spec_method()
{
// use here your cells mocks with $this->cells
// and make predictions on them
}
}
解释
在let
函数中,您实例化了一个Prophet
对象,它基本上是一个与PHPSpec(本身使用Prophecy(协同使用的模拟库/框架
我建议保留实例($this->prophet
(,因为这将对下一步有用。
现在,您必须创建mock,并且可以使用prophet
和prophesize
即使对于mock,我也建议将它们保存在一个私有变量中,您可能在方法中使用该变量进行预测。
letGo
函数用于明确检查您对cells
的期望:如果没有,cells
仅为stubs
或dummies
。
当然,通过方法签名传递mock并显式跳过checkPredictions
是很方便的,但是,一旦您需要一个mock数组,我想这是实现目标的唯一方法。