webentwicklung-frage-antwort-db.com.de

Wie werden Datenbankmigrationen für Laravel-Tests festgelegt?

Laravels Dokumentation empfiehlt die Verwendung des Merkmals DatabaseMigrations für die Migration und das Zurücksetzen der Datenbank zwischen den Tests.

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

Ich habe jedoch einige Startdaten, die ich für meine Tests verwenden möchte. Wenn ich renne:

php artisan migrate --seed

dann funktioniert es für den ersten Test, aber nachfolgende Tests schlagen fehl. Dies liegt daran, dass das Merkmal die Migration rückgängig macht und beim erneuten Ausführen der Migration die Datenbank nicht aussortiert. Wie kann ich die Datenbank-Seeds mit der Migration ausführen?

11
Jeff Puckett

Alles, was Sie tun müssen, ist einen handwerklichen Aufruf db:seed in der Funktion setUp

<?php

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

public function setUp(): void
   {
     parent::setUp();
     $this->artisan('db:seed');
   }

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

ref: https://laravel.com/docs/5.6/testing#creating-and-running-tests

9
lasec0203

Ich musste ein bisschen graben, um das herauszufinden, also dachte ich, ich würde teilen .

Wenn Sie sich den Quellcode für das Merkmal DatabaseMigrations ansehen, werden Sie sehen, dass es eine Funktion hat runDatabaseMigrations , das von setUp aufgerufen wird, das wird vor jedem Test ausgeführt und registriert einen Rückruf, der beim Herunterfahren ausgeführt werden soll.

Sie können das Merkmal sortieren "erweitern" , indem Sie diese Funktion aliasen und eine neue Funktion mit Ihrer Logik deklarieren (artisan db:seed) unter dem ursprünglichen Namen und rufen Sie den darin enthaltenen Alias ​​auf.

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations {
        runDatabaseMigrations as baseRunDatabaseMigrations;
    }

    /**
     * Define hooks to migrate the database before and after each test.
     *
     * @return void
     */
    public function runDatabaseMigrations()
    {
        $this->baseRunDatabaseMigrations();
        $this->artisan('db:seed');
    }

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}
20
Jeff Puckett

Ich weiß, dass diese Frage bereits mehrmals beantwortet wurde, aber ich habe diese bestimmte Antwort nicht gesehen, also dachte ich, ich würde sie einwerfen. 

In laravel (zumindest seit v5.5) gibt es seit einiger Zeit eine Methode in der TestCase-Klasse, die speziell zum Aufrufen eines Datenbanksämpfers verwendet wird:

https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed

mit dieser Methode müssen Sie lediglich $this->seed('MySeederName'); aufrufen, um die Sämaschine auszulösen.

Wenn also diese Sämaschine vor jedem Test ausgelöst werden soll, können Sie Ihrer Testklasse die folgende setUp-Funktion hinzufügen:

public function setUp()
{
    parent::setUp();
    $this->seed('MySeederName');
}

Das Endergebnis ist das gleiche wie:

 $this->artisan('db:seed',['--class' => 'MySeederName'])

oder 

Artisan::call('db:seed', ['--class' => 'MySeederName'])

Aber die Syntax ist (meiner Meinung nach) etwas sauberer.

1
Chris Schmitz

Wenn Sie das Testmerkmal RefreshDatabase verwenden:

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, RefreshDatabase {
        refreshDatabase as baseRefreshDatabase;
    }

    public function refreshDatabase()
    {
        $this->baseRefreshDatabase();

        // Seed the database on every database refresh.
        $this->artisan('db:seed');
    }
}
0
Steve Bauman

Hier ist eine alternative Lösung, falls Sie Artisans native DatabaseMigrations- und Seeder-/Migrationsmethoden umgehen möchten. Sie können Ihre eigene Eigenschaft zum Seeding Ihrer Datenbank erstellen:

namespace App\Traits;

use App\Models\User;
use App\Models\UserType;

trait DatabaseSetup 
{

    public function seedDatabase()
    {
        $user = $this->createUser();
    }

    public function createUser()
    {
        return factory(User::class)->create([
            'user_type_id' => function () {
                return factory(UserType::class)->create()->id;
            }
        ]);
    }

    public function getVar() {
        return 'My Data';
    }
}

Dann nennen Sie es in Ihrem Test so: 

use App\Traits\DatabaseSetup;

class MyAwesomeTest extends TestCase
{
    use DatabaseSetup;
    use DatabaseTransactions;

    protected $reusableVar;

    public function setUp()
    {
        parent::setUp();
        $this->seedDatabase();
        $this->reusableVar = $this->getVar();
    }

    /**
     * @test
     */
    public function test_if_it_is_working()
    {
        $anotherUser = $this->createUser();
        $response = $this->get('/');
        $this->seeStatusCode(200);
    }

}
0
JP Lew