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