PHPSpec не может делать многое из того, что вы можете, например, делать с PHPUnit и Mockery.
Вывод: я бы сказал, что PHPSpec — неподходящий инструмент для тестирования Eloquent.
Внутри Eloquent происходит много 'волшебства', и PHPSpec, похоже, не любит волшебства, если вы чувствуете, что должны использовать PHPSpec для тестирования Eloquent, иначе мир рухнет, то вот пара вещей ты можешь сделать.
Отказ от ответственности: я не призываю вас продолжать использовать PHPSpec для тестирования Eloquent, на самом деле я не хочу, чтобы вы тестировали с его помощью модели Eloquent, я только объясняю некоторые приемы работы вокруг ситуаций, с которыми вы столкнетесь при испытании магических методов и черного искусства — в надежде, что вы сможете применить их где-нибудь еще, когда это будет иметь смысл. Для меня это не имеет смысла в случае с моделями Eloquent.
Итак, вот список:
- Не используйте магические геттеры и сеттеры, вместо этого используйте
getAttribute()
и setAttribute()
- Не используйте магические вызовы для лениво загружаемых отношений, т.е.
$user->profile
. Используйте методы $user->profile()->getResults()
- Создайте фиктивный класс SUT, расширяющий вашу модель, и определите в нем эти методы
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...
}
Спецификация модели продукта
<?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
в классе-приманке и делая их SUT, вы сообщаете PHPSpec, что эти методы действительно существуют в классе. Их аргументы и тип возвращаемого значения не имеют значения, важно только их существование.
Преимущество ?
Теперь в вашей спецификации, когда вы вызываете метод ->where()
или ->latest()
для модели, PHPSpec не будет жаловаться на это, и вы можете изменить методы класса-приманки, чтобы они возвращали, скажем, объект Prophecy
и делали над ним утверждения.
person
Gufran
schedule
16.12.2014