Setting up PHPUnit tests in Laravel

前端 未结 1 1225
忘掉有多难
忘掉有多难 2021-01-04 12:05

I\'m fairly new to unit testing, but I\'ve read pretty much all the documentation on phpunit.de (Up to chapter 10).

It states that testing using databases can be slo

1条回答
  •  清酒与你
    2021-01-04 12:29

    Ok, after a bit of investigating (the classes), I've determined that the Laravel application has not yet been created when the static setUpBeforeClass() method is called.

    The Laravel container is created the first time setUp() is called in \vendor\laravel\framework\src\illuminate\Foundation\Testing\TestCase.php. That's why it works fine when I move my code to the setUp() method.

    The container is then stored in the $app property stored in \vendor\laravel\framework\src\illuminate\Foundation\Testing\ApplicationTrait.php.

    I can manually create a container instance by adding this code to the setUpBeforeClass() method:

    $app = require __DIR__.'/../bootstrap/app.php';
    $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
    

    But this method seems pretty hacky, and I don't like it.

    Instead, I moved the seeding code to the setUp() method, but only seeded the database if the class properties were null. Therefore it only gets seeded on the first call of setUp(). Any subsequent calls do not get seeded:

    class CommentTest extends TestCase
    {
        use DatabaseMigrations;
    
        protected static $blog;
        protected static $comments;
    
        public function setUp()
        {
            parent::setUp();
    
            $this->runDatabaseMigrations();
    
            if (is_null(self::$blog)) {
                self::$blog = factory(App\Models\Content\Blog::class, 1)->create();
                self::$comments = factory(App\Models\Content\Comment::class, 6)->create();
            }
        }
    }
    

    In combination with Laravels DatabaseMigrations trait for testing, This is now the workflow:

    1. PHPUnit is called
    2. The Test class is called, which contains the DatabaseMigrations trait
    3. The database is migrated (tables created)
    4. The setUp() method is called for the first time, which seeds the relevant tables with testing data
    5. The test is run, and and access the test data
    6. There is no tearDown() method invoked, instead the DatabaseMigrations trait simply resets the database, so my test doesn't have to worry about cleaning up the test data.

    EDIT

    In addition, it seems (although I'm not 100%), that if you have a custom setUp() method, you need to manually call runDatabaseMigrations() from the overridden setUp() method:

    public function setUp()
    {
        parent::setUp();
        $this->runDatabaseMigrations();
    
        /** Rest of Setup **/
    }
    

    runDatabaseMigrations() doesn't seem to get called automatically if you overload the setUp() method.

    I hope this helps, but if anyone else has a better solution, please feel free to let me know :)

    0 讨论(0)
提交回复
热议问题