再次对PhpSpec存根和模拟感到困惑

时间:2014-10-22 17:13:30

标签: unit-testing model mocking phpspec laravel-5

我正在构建一个Laravel 5应用程序,并且让我对如何在PhpSpec中模拟事物感到困惑。

我正在构建一个计划时间验证程序,要求根据所有当前计划检查预期的计划,并查看是否存在任何重叠(事件不允许重叠)。

我需要提出有问题的时间表,以便我可以对它们进行测试。目前它是一个非常基本的whereBetween查询,但它会变得更加复杂,因为还会有重复的时间表来检查。

所以这是我的课程。我真的只想测试doesNotOverlap函数。

use App\Schedule;

class ScheduleTimesValidator
{
    protected $schedule;

    public function __construct(Schedule $schedule)
    {
        $this->schedule = $schedule;
    }

    public function doesNotOverlap($slug, $intended)
    {
        $schedules = $this->getSchedulesBetween($slug, $intended);
        if(empty($schedules)) return true;

        return false;
    }

    protected function getSchedulesBetween($slug, $intended)
    {
        // Casting to array to make testing a little easier
        return $this->schedule->whereIsRecurring(false)
                                ->ofChurch($slug)
                                ->whereBetween('start', [$intended['start'], $intended['end']])
                                ->get()->toArray();
    }

这是我的规格

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class ScheduleTimesValidatorSpec extends ObjectBehavior
{
    protected $validIntended = [
        'start' => '2015-12-01 12:00:00',
        'end' => '2015-12-01 13:00:00'
    ];

    protected $churchNonRecurringSchedules = [
        ['start' => '2014-11-20 13:00:00', 'end' => '2014-11-21 14:00:00'],
        ['start' => '2014-11-23 10:36:07', 'end' => '2014-11-23 11:36:07'],
    ];

    function let($schedule)
    {
        $schedule->beADoubleOf('App\Schedule');
        $this->beConstructedWith($schedule);
    }


    function it_is_initializable()
    {
        $this->shouldHaveType('App\Validation\ScheduleTimesValidator');
    }

    function it_should_return_true_if_it_does_not_overlap($schedule)
    {
        // $schedule->any()->willReturn([]);
        // $schedule->whereIsRecurring()->shouldBeCalled();
        // $schedule->whereIsRecurring(false)->ofChurch()->whereBetween()->get()->toArray()->willReturn([]);
        // $schedule->willReturn([]);
        // $this->getSchedulesBetween('slug', $this->validIntended)->willReturn([]);
        $this->doesNotOverlap('slug', $this->validIntended)->shouldReturn(true);
    }

    // Tear Down
    function letgo() {}

}

如果我像我那样运行它:

! it should return true if it does not overlap
    method 'Double\App\Schedule\P8::whereIsRecurring()' not found.

我尝试(如您所见)各种注释掉的东西来模拟$ schedule会返回什么,但这似乎不起作用。

所以我想我想在类中模拟受保护的getSchedulesBetween方法,但是像$this->getSchedulesBetween($arg, $arg)->willReturn(blah)这样的操作不起作用。

我是否需要从类中提取getSchedulesBetween()并将其移到另一个类中然后模拟它?或者我是否需要将$ this-> schedule-> blah推入doestNotOverlap方法,以便我可以模拟$ schedule会返回什么?

我不想实际测试App \ Schedule Laravel模型 - 我只是想模拟它返回的内容,并且将硬编码将运行以获得不同模型结果的各种查询。

这里结束了漫长的一天,所以大脑有点笨拙。

更新2014-10-23

所以我在Schedule模型上创建了一个范围

public function scopeSchedulesBetween($query, $slug, $intended)
{
    return $query->whereIsRecurring(false)
                    ->ofChurch($slug)
                    ->whereBetween('start', [$intended['start'], $intended['end']]);
}

然后创建了一个新的App \ Helpers \ ScheduleQueryHelper,它将App \ Schedule实例化为变量并添加了此方法:

public function getSchedulesBetween($slug, $intended)
{
    return $this->schedule->schedulesBetween($slug, $intended)->get()->toArray();
}

然后更新了我的规范

function let($scheduleQueryHelper)
{
    $scheduleQueryHelper->beADoubleOf('App\Helpers\ScheduleQueryHelper');
    $this->beConstructedWith($scheduleQueryHelper);
}

function it_should_return_true_if_it_does_not_overlap($scheduleQueryHelper)
{
    $scheduleQueryHelper->getSchedulesBetween('slug', $this->validIntended)->willReturn([]);
    $this->doesNotOverlap('slug', $this->validIntended)->shouldReturn(true);
}

然后在我的ScheduleTimesValidator类中做了

public function doesNotOverlap($slug, $intended)
{
    $schedules = $this->scheduleQueryHelper->getSchedulesBetween($slug, $intended);

    if(empty($schedules)) {
        return true;
    }

    return false;
}

现在PhpSpec正在嘲笑其他课程。然而,这似乎是一种非常迂回的做事方式。

0 个答案:

没有答案