PHPSpec は、たとえば PHPUnit や Mockery で実行できる多くのことを実行できません。
結論: PHPSpec は Eloquent をテストするための適切なツールではないと思います。
Eloquent の内部では多くの「魔法」が起こっており、PHPSpec は魔法を好まないようです。Eloquent をテストするために PHPSpec を使用する必要があると感じた場合、そうしないと世界が粉々になってしまうと感じた場合は、次の 2 つの方法を実行できます。
免責事項: Eloquent のテストに PHPSpec を使用することを推奨しているわけではありません。実際、PHPSpec を使用して雄弁なモデルをテストすることは望ましくありません。魔法のメソッドのテスト中に遭遇する状況を回避するためのいくつかのトリックを説明しているだけです。そしてブラックアート-それが理にかなっているときに他の場所に適用できることを願って. 私には、Eloquent モデルの場合は意味がありません。
リストは次のとおりです。
- 魔法のゲッターとセッターを使用せず
getAttribute()
、setAttribute()
代わりにand を使用してください
- 遅延ロードされたリレーションにマジック コールを使用しないでください
$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
おとりクラスでandメソッドを定義しlatest
て SUT にすることで、これらのメソッドが実際にクラスに存在することを PHPSpec に知らせます。それらの引数と戻り値の型は重要ではなく、存在のみが重要です。
アドバンテージ ?
これで、仕様でモデルの呼び出し->where()
または->latest()
メソッドを実行しても、PHPSpec はそれについて文句を言うことはありません。おとりクラスのメソッドを変更して、たとえばオブジェクトを返し、それに対してProphecy
アサーションを行うことができます。