如何在PHPSpec中创建一系列模拟?

时间:2016-09-28 14:05:15

标签: php unit-testing phpspec

我刚刚开始使用PHPSpec,我真的非常喜欢PHPUnit,特别是那些不费力的模拟和存根。无论如何,我正在尝试测试的方法需要一组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 spec\MyThing\Row;

use MyThing\Cell;
use PhpSpec\ObjectBehavior;

class RowSpec extends ObjectBehavior
{
    function let()
    {
        // need to get an array of Cell objects
        $this->beConstructedWith($cells);
    }

    function it_is_initializable()
    {
        $this->shouldHaveType('MyThing\Row');
    }

    // ...
}

我曾希望我能做到以下几点,但它却抱怨找不到Cell[]。使用FQN,它抱怨无法找到\MyThing\Cell[]

/**
 * @param Cell[] $cells
 */
function let($cells)
{
    // need to get an array of Cell objects
    $this->beConstructedWith($cells);
}

我能解决的唯一选择是传递多个类型提示的Cell参数并手动将它们组合成一个数组。我错过了一些简单的东西吗?

编辑:我正在使用PHPSpec 2.5.3,不幸的是服务器目前停留在PHP 5.3: - (

1 个答案:

答案 0 :(得分:1)

为什么不做

之类的事情
use Prophecy\Prophet;
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),这对后续步骤很有用。

现在,你必须创建你的模拟,你可以使用prophetprophesize
即使对于模拟,我建议将它们保存为一个私有变量,你可能用于方法中的预测。

letGo函数可以明确检查您对cells的期望:不,cells仅为stubsdummies

当然,通过方法签名模拟并明确跳过checkPredictions很方便,但是,只要你需要一系列模拟,我想这是达到你的唯一方法目标