murave

Laravelのテスト用便利トレイトの動作を変えてみる

Laravel 5.5 です。

Laravelにはunit test等の際にuseするとよろしくやってくれるトレイトがあります。
昨日の記事に出てきたRefreshDatabaseやDatabaseMigrations、他にはDatabaseTransactions、WithoutMiddleware、WithoutEventsがあります。

本当に便利なのですが、すこし動作を調整したいこともあります。

例えばDatabaseMigrationsでマスターの流し込みまでやりたいとか。

フレームワーク内を調べるとsetUpTraits()でトレイトがuseされたかを判定し、特定のメソッドを呼ぶようになっていることがわかります。

protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));

if (isset($uses[RefreshDatabase::class])) {
$this->refreshDatabase();
}

if (isset($uses[DatabaseMigrations::class])) {
$this->runDatabaseMigrations();
}

if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}

if (isset($uses[WithoutMiddleware::class])) {
$this->disableMiddlewareForAllTests();
}

if (isset($uses[WithoutEvents::class])) {
$this->disableEventsForAllTests();
}

return $uses;
}
このメソッドをapp/tests/TestCase.phpやDuskTestCase.phpでオーバーライドして自分が作ったトレイトを実行するようにもできます。

例えば私の場合、データベースダンプをリストアするSnapshotLoadというトレイトを作成して追加しています。

protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[SnapshotLoad::class])) {
// DatabaseTransactionsの前に実行する必要がある。
$this->runSnapshotLoad();
}
return parent::setUpTraits();
}
閑話休題、前回記事の最後のテストサンプルでのDatabaseMigrationsの動作を変更してみましょう。呼び出されるrunDatabaseMigrationsメソッドを別名に変更し、新たに定義します。

<?php
namespace Tests\Browser;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use App\User;

class LoginTest extends DuskTestCase
{
use DatabaseMigrations
{
runDatabaseMigrations as runDatabaseMigrationsOrg; //名前変える
}
//DatabaseMigrationsの動作カスタマイズ
public function runDatabaseMigrations()
{
$this->runDatabaseMigrationsOrg(); //元々の処理を実行
\Artisan::call('db:seed', ['--class' => 'MasterSeeder']);
}

public function testLogin()
{
$user = factory(User::class)->create();

$this->browse(function (Browser $browser) use ($user) {
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'secret')
->press('ログイン')
->assertPathIs('/home');
});
}
}
元々のDatabaseMigrationsの処理後にマスター設定用のMasterSeederが実行されます。