如果我无法访问或使用任何 Eloquent 方法,使用 PHPSpec 有什么意义?
例如:($this引用雄辩Product
模型(
function it_removes_property(PropertyValueInterface $property)
{
$this->addProperty($property);
$this->properties->shouldHaveCount(1);
$this->removeProperty($property);
$this->properties->shouldHaveCount(0);
}
这在方法addProperty
中不起作用,removeProperty
有对各种 Eloquent 集合和模型函数的调用,似乎 PHPSpec 无法处理这个问题,即使所有这些类都包含在 use
语句中。
我注意到在Jeffery Way对Laracasts的屏幕投射中,他从未使用过真正的Eloquent模型。他只使用普通的PHP对象。这有什么意义呢?那不是真实的世界。
这也与正确引用雄辩的模型类无关,因为我已经在这样做use Illuminate'Database'Eloquent'Model;
此外,我从不使用外墙。所以也不是那样。
PHPSpec 无法做很多你可以做的事情,例如,使用 PHPUnit 和 Mockery。
一句话:我会说PHPSpec不是测试Eloquent的正确工具。
似乎不喜欢魔法,如果你觉得你必须使用 PHPSpec 来测试 Eloquent 否则世界会破碎,那么这里有几件事你可以做。
免责声明:我并不是鼓励你继续使用 PHPSpec 进行 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
的对象并对其做出断言。