Laravel 5 Повторное заполнение базы данных для модульного тестирования между тестами

Я начинаю с заполненной базы данных и пытаюсь повторно заполнить базу данных между модульными тестами в Laravel 5. Насколько я понимаю, в Laravel 4 вы можете просто использовать Illuminate\Support\Facades\Artisan и запускать команды

Artisan::call('migrate');
Artisan::call('db:seed');

или вы могли бы сделать:

$this->seed('DatabaseSeeder');

перед каждым испытанием. В Laravel 5 это, похоже, было заменено на

use DatabaseMigrations;

or

use DatabaseTransactions;

Я пытался использовать их, и мне удалось получить тесты для переноса базы данных; однако на самом деле он не повторно заполняет данные в таблицах. Я прочитал несколько форумов, жалующихся на это, и пробовал несколько разных подходов, вызывая их из TestCase и внутри каждого теста... добавляя

    $this->beforeApplicationDestroyed(function () {
        Artisan::call('migrate');
        Artisan::call('migrate:reset');
        Artisan::call('db:seed');
        DB::disconnect();
    });

в TestCase.php tearDown()...

Я также попытался добавить

$this->createApplication();

к методу, вызываемому в каждом тесте из TestCase.php

Иногда он просто полностью стирает мои таблицы. Ничто из того, что я нахожу на сайте Laravel или в блогах, похоже, не работает. Отчасти это, вероятно, потому, что я, вероятно, пробую методы Laravel 4 в Laravel 5. Есть ли способ сделать это в Laravel 5?

Мой код для testcase.php выглядит так:

<?php

use Illuminate\Support\Facades\Artisan as Artisan;

class TestCase extends Illuminate\Foundation\Testing\TestCase{

    use Illuminate\Foundation\Testing\WithoutMiddleware;
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Illuminate\Foundation\Testing\DatabaseTransactions;

    protected $baseUrl = 'http://localhost';


    public function initializeTests(){

        $this->createApplication();

       Artisan::call('migrate');
       $this->artisan('migrate');
       Artisan::call('db:seed');
       $this->artisan('db:seed');
       $this->seed('DatabaseSeeder');
       $this->session(['test' => 'session']);
       $this->seed('DatabaseSeeder');

    }

    public function tearDown()
    {
      Mockery::close();
      Artisan::call('migrate:reset');
      $this->artisan('migrate:reset');
      Artisan::call('migrate:rollback');
      $this->artisan('migrate:rollback');
      Artisan::call('migrate');
      $this->artisan('migrate');
      Artisan::call('db:seed');
      $this->artisan('db:seed');
      $this->seed('DatabaseSeeder');
      DB::disconnect();

         foreach (\DB::getConnections() as $connection) {
             $connection->disconnect();
         }

      $this->beforeApplicationDestroyed(function () {
         Artisan::call('migrate:reset');
         $this->artisan('migrate:reset');
         Artisan::call('migrate:rollback');
         $this->artisan('migrate:rollback');
         Artisan::call('migrate');
         $this->artisan('migrate');
         Artisan::call('db:seed');
         $this->artisan('db:seed');
         $this->seed('DatabaseSeeder');
         DB::disconnect();
         foreach (\DB::getConnections() as $connection) {
             $connection->disconnect();
         }
      });

       $this->flushSession();
       parent::tearDown();


    }

    public function getConnection()
    {
        $Connection = mysqli_connect($GLOBALS['DB_DSN'], $GLOBALS['DB_USERNAME'], $GLOBALS['DB_PASSWORD'], $GLOBALS['DB_DATABASE']);
        $this->createDefaultDBConnection();
        return $this->Connection;
    }

    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

        return $app;
    }

    /**
     * Magic helper method to make running requests simpler.
     *
     * @param $method
     * @param $args
     * @return \Illuminate\Http\Response
     */
    public function __call($method, $args)
    {
        if (in_array($method, ['get', 'post', 'put', 'patch', 'delete']))
        {
            return $this->call($method, $args[0]);
        }

        throw new BadMethodCallException;
    }

    /**
     * Create a mock of a class as well as an instance.
     *
     * @param $class
     * @return \Mockery\MockInterface
     */
    public function mock($class)
    {
        $mock = Mockery::mock($class);

        $this->app->instance($class, $mock);

        return $mock;
    }

}

Мой тест выглядит примерно так

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Artisan;

class CustomerRegistrationControllerTest extends TestCase
{

    use DatabaseMigrations;

    protected static $db_inited = false;

    protected static function initDB()
    {
        echo "\n---Customer Registration Controller Tests---\n"; // proof it only runs once per test TestCase class
        Artisan::call('migrate');
        Artisan::call('db:seed');
    }

    public function setUp()
    {

        parent::setUp();

        if (!static::$db_inited) {
            static::$db_inited = true;
            static::initDB();
        }

//        $this->app->refreshApplication();
        $this->artisan('migrate:refresh');
        $this->seed();
        $this->seed('DatabaseSeeder');

        $this->initializeTests();

);

    }


    public function testSomething()

    {


        $this->Mock
            ->shouldReceive('destroy')
            ->with('1')
            ->andReturn();


        $this->RegistrationController->postRegistration();
//      $this->assertResponseStatus(200);

    }

}

person Nabsta    schedule 04.02.2016    source источник
comment
Может быть, эта ссылка поможет laracasts.com/discuss/channels/tips/   -  person Raftalks    schedule 19.03.2016


Ответы (2)


Просто запустите это:

    $this->artisan('migrate:refresh', [
        '--seed' => '1'
    ]);

Чтобы избежать сохранения изменений в базе данных между тестами, добавьте use DatabaseTransactions к своим тестам, которые затрагивают базу данных.

person Webnet    schedule 23.09.2016

Почему бы не создать собственную команду, например db:reset. Эта команда либо усекает все ваши таблицы, либо удаляет/создает схему, а затем выполняет миграцию.

В своем тесте вы затем используете: $this->call('db:reset') между вашими тестами

person jeremy_nikolic    schedule 07.09.2016