PHPSpec не в состоянии сделать много вещей, которые вы можете, например, делать с PHPUnit и Mockery.
Итог: я бы сказал, что PHPSpec - это не подходящий инструмент для тестирования Eloquent.
Существует много «магия» происходит внутри красноречивый и PHPSpec, кажется, не нравится магия, если вы чувствует, как вы должны использовать PHPSpec для тестирования красноречивы или мир разрушится, то вот несколько вещей, ты можешь сделать.
Отказ от ответственности:Я не призываю вас идти вперед и использовать PHPSpec для красноречивого тестирования, на самом деле я не хочу, чтобы вы протестировать красноречивые модели с ней, я только объяснить некоторые уловки, чтобы обойти ситуации вы столкнетесь при тестировании магических методов и черного искусства - в надежде, что вы сможете применить их где-нибудь еще, когда это имеет смысл. Для меня это не имеет смысла в случае моделей Eloquent.
Так вот список:
- Не использовать магические методы получения и установки, используйте
getAttribute()
и setAttribute()
вместо
- Не используйте магию вызовы лениво загружены отношения, т.е.
$user->profile
. Способы использования $user->profile()->getResults()
- Создайте класс SUT mock, расширяющий вашу модель и определяющий те методы
where
на ней, а также определите методы области и все остальное, что Eloquent должен делать для вас «магически».
- Используйте метод
beAnInstanceOf()
, чтобы переключиться на макет и сделать на нем утверждения.
Вот пример того, как мой тест будет выглядеть так:
Модель продукта
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function scopeLatest($query)
{
return $query->where('created_at', '>', new Carbon('-1 week'))
->latest();
}
// Model relations here...
}
Spec для продукта Модель
<?php namespace Spec\Model;
use Prophecy\Argument;
use App\Entities\Product;
use PhpSpec\ObjectBehavior;
class ProductSpec extends ObjectBehavior
{
public function let()
{
$this->beAnInstanceOf(DecoyProduct::class);
}
public function it_is_initializable()
{
$this->shouldHaveType('Product');
}
}
// Decoy Product to run tests on
class DecoyProduct extends Product
{
public function where();
// Assuming the Product model has a scope method
// 'scopeLatest' on it that'd translate to 'latest()'
public function latest();
// add other methods similarly
}
Определяя where
и latest
метод класса decoy и делает его SUT, вы позволяете PHPSpec знать, что эти методы действительно существуют в классе. Их аргументы и тип возврата не имеют значения, только существование.
Преимущество?
Теперь, когда вы вызываете метод ->where()
или ->latest()
, модель PHPSpec не будет жаловаться на это, и вы можете изменить методы класса decoy, чтобы вернуть, скажем, объект Prophecy
и сделать на нем утверждения.