Search code examples
phplaravelphpunitdatabase-migration

Laravel phpunit how to use diffent migrations for tests


I am trying to set up tests in Laravel, but I want to run different migrations from those that usually run.

The migrations that I run to initiate the database imports data from a production environment.
For testing I want to use a different database called "test", and I want to fill this test database with test data, not production data.

I added a "testing" connection to config/database.php which uses the "test" database:

'connections' => [

        'mysql' => [
            'database' => env('DB_DATABASE', 'forge'),
            ...
        ],

        'testing' => [
            'database' => 'test',
            ...
        ],
],

And I setup phpunit.xml to use this "testing" connection:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit ...>
    ...
    <php>
        <env name="DB_CONNECTION" value="testing"/>
        ...
    </php>
</phpunit>

Now I want to initialize this "test" database with test data, using migrations from a different folder than the default.

I can use the normal migrations like this:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;

abstract class TestCase extends BaseTestCase
{
    use DatabaseMigrations;

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

But this uses the default folder database/migrations. I would like to put the testing migrations in folder tests/database/migrations.

Is there a way to let use DatabaseMigrations; use migrations from another folder?


Solution

  • You might need to override runDatabaseMigrations method in DatabaseMigrations trait and set the app's database path from there before your migrations run.

    The runDatabaseMigrations method might end up looking like this:

    use DatabaseMigrations { runDatabaseMigrations as runMigration; }
    
        public function runDatabaseMigrations()
        {
            $this->app->useDatabasePath(base_path('tests/database')); //example path
    //        dump($this->app->databasePath());
            $this->runMigration();
        }
    

    Or you can set in the boot method of your AppService provider:

        if (config('app.env') === 'testing') { //Laravel automatically set env to 'testing' when running test
            $this->app->useDatabasePath(base_path('tests/database'));
        }
    

    The migration will look for a sub-folder of 'tests/database' called "migrations".

    PS: There will be side effect to this if you're have some other code or folder in the default database folder. Example, your factory class there will not be found for this test class.