LoginSignup
6
2

More than 5 years have passed since last update.

Laravel5.5 Seederで単体テストのテストデータを登録してみる

Last updated at Posted at 2017-09-21

概要

Laravel5.2の時にやってたテストデータの登録方法が上手くいかず、少しハマったのでそのまとめ。

環境

Laravel 5.5.9
PHP 7.1.3
MySQL 5.7.19

Laravel5.2の時の方法

確かこんな感じで、@beforeアノテーションでテスト前にSeederを実行してました。

tests\Unit\ExampleTest.php
<?php

namespace Tests\Unit;

use Illuminate\Database\Seeder;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * @before
     */
    public function setUpFixtures()
    {
        $this->seed(__CLASS__ . 'Seeder');
    }

    /**
     * @test
     */
    public function サンプルテスト()
    {
        $this->markTestIncomplete('テストを実装する!');
    }
}

/**
 * テストデータ登録Seeder
 */
class ExampleTestSeeder extends Seeder
{
    public function run()
    {
        // @todo テストデータ登録
    }
}

Laravel5.5でも同様にやってみる

RefreshDatabaseトレイトが追加されてるので、ついでに変更。

tests\Unit\ExampleTest.php
<?php

namespace Tests\Unit;

use Illuminate\Database\Seeder;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * @before
     */
    public function setUpFixtures()
    {
        $this->seed(__CLASS__ . 'Seeder');
    }

    /**
     * @test
     */
    public function サンプルテスト()
    {
        $this->markTestIncomplete('テストを実装する!');
    }
}

/**
 * テストデータ登録Seeder
 */
class ExampleTestSeeder extends Seeder
{
    public function run()
    {
        // @todo テストデータ登録
    }
}

結果

エラーが発生。
どうもアプリケーションクラスの初期化が終わってないっぽい。
アプリケーションの初期化の方法が変わったのかな?(後で調べて追記するかも)

1) Tests\Unit\ExampleTest::サンプルテスト
Error: Call to a member function call() on null

(追記:2017-09-22)
PHPUnit側の処理が変わったみたい。(PHPUnit\Util\Test::getHookMethodsメソッド)
(PHPUnitのバージョンによって挙動が変わるなら、サンプルソースも問題なので修正しました)


原因

ソースをみた感じだと、setUpメソッド内でアプリケーションの初期化を行なっているが、PHPUnit的にはsetUpより@beforeアノテーションで定義したものが先に呼ばれる模様。
array_shift array_unshiftで、見つかった@beforeのメソッドを格納してるので、後に見つかったものが先に呼ばれるっぽい。そしてデフォルト値にsetUpが入っている。)

 Laravel5.5で動くよう修正

afterApplicationCreatedメソッドでアプリケーションの初期化完了時のコールバックを定義できるみたい。

tests\Unit\ExampleTest.php
<?php

namespace Tests\Unit;

use Illuminate\Database\Seeder;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * @before
     */
    public function setUpFixtures()
    {
        // 下のように書き換え
        //$this->seed(__CLASS__ . 'Seeder');

        // 訂正(2017-09-22)
        //$this->afterApplicationCreated(function() {
        //    $this->seed(__CLASS__ . 'Seeder');
        //});
        if ($this->setUpHasRun) {
            // アプリケーションのセットアップが完了しているならそのまま実行
            $this->seed(__CLASS__ . 'Seeder');
        } else {
            // アプリケーションのセットアップが完了していないならコールバックで設定
            $this->afterApplicationCreated(function() {
                $this->seed(__CLASS__ . 'Seeder');
            });
        }
    }

    /**
     * @test
     */
    public function サンプルテスト()
    {
        $this->markTestIncomplete('テストを実装する!');
    }
}

/**
 * テストデータ登録Seeder
 */
class ExampleTestSeeder extends Seeder
{
    public function run()
    {
        // @todo テストデータ登録
    }
}

再度実行して動くことを確認。

$ vendor/bin/phpunit 
PHPUnit 6.3.0 by Sebastian Bergmann and contributors.

I                                                                   1 / 1 (100%)

Time: 580 ms, Memory: 12.00MB

OK, but incomplete, skipped, or risky tests!
Tests: 1, Assertions: 0, Incomplete: 1.

まとめ

setUp() > @before > テスト実行 の順だと思い込んでた...
(2017-09-22)
追記しましたが、PHPUnitのバージョンで挙動が変わるっぽい。
ちゃんと確認してよかった。。サンプルソースも修正しました。

内容に間違いがあるとか、もっと良い方法があるとか、何かあればご指摘ください。

以上です。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2