1

我目前正在构建一个 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 推入 dotNotOverlap 方法,以便模拟 $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 正在嘲笑其他类。然而,这似乎是一种非常迂回的做事方式。

4

0 回答 0