我正在构建一个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模型 - 我只是想模拟它返回的内容,并且将硬编码将运行以获得不同模型结果的各种查询。
这里结束了漫长的一天,所以大脑有点笨拙。
所以我在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正在嘲笑其他课程。然而,这似乎是一种非常迂回的做事方式。