6

I start with a seeded database and am trying to reseed the database between unit tests in Laravel 5. In Laravel 4 I understand you could simply use Illuminate\Support\Facades\Artisan and run the commands

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

or you supposedly could do:

$this->seed('DatabaseSeeder');

before every test. In Laravel 5 this appears to have been replaced by

use DatabaseMigrations;

or

use DatabaseTransactions;

I have tried using these and have managed to get the tests to migrate the database; however, it doesn't actually reseed the data in the tables. I have read through several forums complaining about this and have tried several different approaches calling these from the TestCase and inside every Test...adding the

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

to the TestCase.php tearDown()...

I have also tried adding

$this->createApplication();

to a method called in every test from TestCase.php

Sometimes it just wipes my tables out completely. Nothing I am finding on Laravel's site or in blogs seems to work. Part of it is probably because I'm probably trying Laravel 4 methods in Laravel 5. Is there any way to do this in Laravel 5?

My code for the testcase.php looks like:

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

}

My Test looks something like

<?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);

    }

}
1

2 Answers 2

2

Just run this:

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

To avoid changes to the database persisting between tests add use DatabaseTransactions to your tests that hit the database.

Sign up to request clarification or add additional context in comments.

Comments

-1

Why not create your own command like db:reset. This command either truncate all your tables or drop/create schema and then migrate.

In your test you then use: $this->call('db:reset') in between your tests

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.