user3871
user3871

Reputation: 12708

Use existing migrations tables for laravel unit testing

I want to use an existing set of migrations to create tables for me to stuff seed data into. I am using Orchestra Testbench for testing. Examples like this show creating the table on the fly:

DB::schema()->create('oauth_identities', function($table) {...

But I want to use existing migrations.

TestCase.php:

use Orchestra\Testbench\TestCase as OrchestraTestCase;

abstract class TestCase extends OrchestraTestCase
{
    protected function getBasePath()
    {
        // reset base path to point to our package's src directory
        return __DIR__ . '/../vendor/orchestra/testbench/fixture';
    }
}

DBTestCase.php:

class DBTestCase extends TestCase { protected $artisan;

/*
 * Bootstrap the application
 */
public function setUp()
{
    parent::setUp();

    $this->artisan = $this->app->make('Illuminate\Contracts\Console\Kernel');

    $this->artisan('migrate', [
            '--database' => 'testbench',
            '--realpath' => realpath(__DIR__.'/../database/migrations'),
        ]
    );

}

protected function getEnvironmentSetUp($app)
{
    parent::getEnvironmentSetUp($app);

    $app['config']->set('database.default', 'testbench');
    $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => ''
        ]
    );
}

UserTest.php:

class UserTest extends DBTestCase
{
    use DatabaseMigrations;

   private function seedUser()
   {

       return [
           'email' => 'myemail',
            ...
       ];
       ...
   }

...
public function testCreateUser()
{
    $user = User::create($this->seedUser());

    die(print_r($user)); 
    ...

Error:

In \App\Tests\UserTest::testCreateUser General error: 1 no such table: users

But in my migrations, I am definitely creating the table:

Schema::create('users', function (Blueprint $table) {...

So how can I use existing migration tables and generate seed data for the migration?


Edit: now when running phpunit after setting my DB driver in DBTestCase, 'driver' => 'sqlite',, it throws error:

Class 'Doctrine\DBAL\Driver\PDOSqlite\Driver' not found in .../Database/SQLiteConnection.php

Navigating to SQLiteConnection.php, the PDOSqlite in use Doctrine\DBAL\Driver\PDOSqlite\Driver as DoctrineDriver; is highlighted in red, saying it's an undefined namespace.

I have this available as a driver in my database.php:

Database.php:

'default' => env('DB_CONNECTION', 'mysql'),

'connections' => [

    'sqlite' => [
        'driver'   => 'sqlite',
        'database' => storage_path('database.sqlite'),
        'prefix'   => '',
    ],

Upvotes: 4

Views: 3422

Answers (2)

Adam
Adam

Reputation: 28968

Assuming that you have setup the ServiceProvider correctly in your package and also pointed to your migration files with loadMigrationsFrom inside the boot method, then you just need to change your test class like this:

class TestCase extends \Orchestra\Testbench\TestCase
{
    public function setUp(): void
    {
        parent::setUp();

        $this->artisan('migrate', ['--database' => 'testbench'])->run();
    }

    /**
     * add the package provider
     *
     * @param $app
     * @return array
     */
    protected function getPackageProviders($app)
    {
        return [\Vendor\Your-Packagename::class];
    }


    /**
     * Define environment setup.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    protected function getEnvironmentSetUp($app)
    {
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => '',
        ]);
    }

Upvotes: 1

Tim
Tim

Reputation: 5933

In case you are using Laravel 5 you can set up your test cases to use data migrations like this:

<?php

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

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

By using the DatabaseMigration trait the database is migrated before each test case and rolled back after it. Please remember this if you try testing the same data in different test cases.

Upvotes: 0

Related Questions