Reputation: 4908
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?
Upvotes: 6
Views: 7416
Reputation: 21
The RefreshDatabase
trait has a method called migrateUsing
which will overload the parameters that it uses when running the migrations. I changed to a specific test migration file for a single test by passing it in as the --path
parameter to the migration.
namespace Tests\Unit;
use Tests\TestCase;
use App\Models\Traits\HasUuid;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\RefreshDatabase;
class HasUuidTest extends TestCase
{
use RefreshDatabase;
protected function migrateUsing()
{
return [
'--path' => 'tests/migrations/2022_03_15_220516_create_test_uuid_table.php'
];
}
public function test_has_uuid()
{
$model = new TestUuid;
$this->assertEmpty($model->id);
$model->save();
$this->assertNotEmpty($model->id);
}
}
class TestUuid extends Model
{
use HasUuid;
}
Upvotes: 1
Reputation: 7334
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.
Upvotes: 11
Reputation: 18976
Artisan migrate has a path option, you have to make your own trait to have similar functionality. I'm thinking something like this.
trait PathDatabaseMigrations {
public function runDatabaseMigrations()
{
// optimal
$path = 'tests/database/migrations';
$this->artisan('migrate:fresh', ['--path' => $path,]);
$this->app[Kernel::class]->setArtisan(null);
$this->beforeApplicationDestroyed(function () {
$this->artisan('migrate:rollback', ['--path' => $path,]);
RefreshDatabaseState::$migrated = false;
});
}
}
Upvotes: 1