web-dev-qa-db-fra.com

Comment amorcer les migrations de bases de données pour les tests laravel?

Laravel's documentation recommande d'utiliser le trait DatabaseMigrations pour la migration et la restauration de la base de données entre les 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('/');

        // ...
    }
}

Cependant, j'ai quelques données de base que j'aimerais utiliser avec mes tests. Si je cours:

php artisan migrate --seed

cela fonctionne ensuite pour le premier test, mais échoue pour les tests suivants. Cela est dû au fait que le trait annule la migration et que, lorsqu'il l'exécute à nouveau, il ne sème pas la base de données. Comment puis-je exécuter les graines de la base de données avec la migration?

11
Jeff Puckett

Tout ce que vous avez à faire est de faire un appel artisan db:seed dans la fonction 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

Il m'a fallu un peu de temps pour comprendre cela, alors je pensais partager .

Si vous examinez le code source du trait DatabaseMigrations , vous verrez qu'il a une fonction runDatabaseMigrations qui est invoquée par setUp qui est exécuté avant chaque test et enregistre rappel à exécuter lors du démontage.

Vous pouvez trier "étendre" le trait en créant un alias pour cette fonction, en déclarant une nouvelle fonction contenant votre logique (artisan db:seed) sous le nom d'origine et en appelant l'alias qui s'y trouve.

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('/');

        // ...
    }
}
16
Jeff Puckett

Je sais que cette question a déjà reçu une réponse à plusieurs reprises, mais comme je n’avais pas vu cette réponse en particulier, j’ai pensé la poser. 

Pendant un certain temps dans laravel (au moins depuis la version 5.5), une méthode de la classe TestCase a été utilisée spécifiquement pour appeler un séparateur de base de données:

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

avec cette méthode, il vous suffit d’appeler $this->seed('MySeederName'); pour faire virer le semoir.

Donc, si vous voulez que ce semoir se déclenche avant chaque test, vous pouvez ajouter la fonction setUp suivante à votre classe de test:

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

Le résultat final est le même que:

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

ou 

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

Mais la syntaxe est un peu plus propre (à mon avis).

1
Chris Schmitz

Si vous utilisez le trait de test RefreshDatabase:

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

Voici une solution alternative, au cas où vous préféreriez contourner les méthodes natives DatabaseMigrations et Seeder/Migration d’Artisan. Vous pouvez créer votre propre trait pour ensemencer votre base de données:

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';
    }
}

Puis appelez-le dans votre test comme ceci: 

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