0

如果我无法访问或使用任何 Eloquent 方法,那么使用 PHPSpec 有什么意义?

例如:($this 指的是 EloquentProduct模型)

function it_removes_property(PropertyValueInterface $property)
{        
    $this->addProperty($property);
    $this->properties->shouldHaveCount(1);

    $this->removeProperty($property);
    $this->properties->shouldHaveCount(0);
} 

这在方法中不起作用,addProperty并且removeProperty调用了各种 Eloquent Collection 和 Model 函数,似乎 PHPSpec 无法处理这个问题,即使所有这些类都包含在use语句中。

我注意到 Jeffery Way 在 Laracasts 上的屏幕投射中,他从不使用真正的 Eloquent 模型。他只使用普通的 PHP 对象。那有什么意义呢?那不是真实的世界。

这也与正确引用雄辩的模型类无关,因为我已经这样做了use Illuminate\Database\Eloquent\Model;

此外,我从不使用外墙。所以它也不是。

4

1 回答 1

3

PHPSpec 不能做很多你可以做的事情,例如,用 PHPUnit 和 Mockery 做的事情。
底线:我想说 PHPSpec 不是测试 Eloquent 的正确工具。

Eloquent 内部发生了很多“魔法”,而 PHPSpec 似乎并不喜欢魔法,如果您觉得必须使用 PHPSpec 来测试 Eloquent,否则世界将崩溃,那么您可以做一些事情。

免责声明: 我不鼓励你继续使用 PHPSpec 进行 Eloquent 测试,事实上我不希望你用它来测试 eloquent 模型,我只是解释一些技巧来解决你在测试魔法方法时会遇到的情况和黑色艺术——希望你能在有意义的时候将它们应用到其他地方。对我来说,在 Eloquent 模型的情况下它没有意义。

所以这里是列表:

  • 不要使用魔法 getter 和 setter,使用getAttribute()andsetAttribute()代替
  • 不要对延迟加载的关系使用魔术调用,即$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
}

通过在诱饵类上定义whereandlatest方法并将其设置为 SUT,您可以让 PHPSpec 知道这些方法实际上存在于类中。它们的参数和返回类型无关紧要,只有存在。

优势 ?
现在,在您的规范中,当您在模型上调用->where()->latest()方法时,PHPSpec 不会抱怨它,您可以更改诱饵类上的方法以返回一个对象Prophecy并对其进行断言。

于 2014-12-16T10:01:03.927 回答