Laravel phpunit 如何使用不同的迁移进行测试
Laravel phpunit how to use diffent migrations for tests
我正在尝试在 Laravel 中设置测试,但我想要 运行 与通常 运行.
不同的迁移
我运行启动数据库的迁移从生产环境导入数据。
为了进行测试,我想使用一个名为 "test" 的不同数据库,并且我想用测试数据而不是生产数据填充这个测试数据库。
我向 config/database.php
添加了一个 "testing" 连接,它使用 "test" 数据库:
'connections' => [
'mysql' => [
'database' => env('DB_DATABASE', 'forge'),
...
],
'testing' => [
'database' => 'test',
...
],
],
我设置 phpunit.xml
以使用此 "testing" 连接:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit ...>
...
<php>
<env name="DB_CONNECTION" value="testing"/>
...
</php>
</phpunit>
现在我想用测试数据初始化这个 "test" 数据库,使用来自不同于默认文件夹的迁移。
我可以像这样使用正常的迁移:
<?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();
}
}
但这使用默认文件夹 database/migrations
。
我想将测试迁移放在文件夹 tests/database/migrations
.
中
有没有办法让 use DatabaseMigrations;
使用来自另一个文件夹的迁移?
您可能需要覆盖 DatabaseMigrations
特征中的 runDatabaseMigrations
方法,并在迁移之前从那里设置应用程序的数据库路径 运行。
runDatabaseMigrations
方法最终可能如下所示:
use DatabaseMigrations { runDatabaseMigrations as runMigration; }
public function runDatabaseMigrations()
{
$this->app->useDatabasePath(base_path('tests/database')); //example path
// dump($this->app->databasePath());
$this->runMigration();
}
或者您可以在您的 AppService 提供者的 boot
方法中设置:
if (config('app.env') === 'testing') { //Laravel automatically set env to 'testing' when running test
$this->app->useDatabasePath(base_path('tests/database'));
}
迁移将查找 'tests/database' 的子文件夹 "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.
Artisan migrate 有一个路径选项,你必须让你自己的特征具有类似的功能。我在想这样的事情。
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;
});
}
}
RefreshDatabase
trait 有一个名为 migrateUsing
的方法,它会重载它在 运行 迁移时使用的参数。我将单个测试的特定测试迁移文件作为 --path
参数传递给迁移。
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;
}
我正在尝试在 Laravel 中设置测试,但我想要 运行 与通常 运行.
不同的迁移我运行启动数据库的迁移从生产环境导入数据。
为了进行测试,我想使用一个名为 "test" 的不同数据库,并且我想用测试数据而不是生产数据填充这个测试数据库。
我向 config/database.php
添加了一个 "testing" 连接,它使用 "test" 数据库:
'connections' => [
'mysql' => [
'database' => env('DB_DATABASE', 'forge'),
...
],
'testing' => [
'database' => 'test',
...
],
],
我设置 phpunit.xml
以使用此 "testing" 连接:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit ...>
...
<php>
<env name="DB_CONNECTION" value="testing"/>
...
</php>
</phpunit>
现在我想用测试数据初始化这个 "test" 数据库,使用来自不同于默认文件夹的迁移。
我可以像这样使用正常的迁移:
<?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();
}
}
但这使用默认文件夹 database/migrations
。
我想将测试迁移放在文件夹 tests/database/migrations
.
有没有办法让 use DatabaseMigrations;
使用来自另一个文件夹的迁移?
您可能需要覆盖 DatabaseMigrations
特征中的 runDatabaseMigrations
方法,并在迁移之前从那里设置应用程序的数据库路径 运行。
runDatabaseMigrations
方法最终可能如下所示:
use DatabaseMigrations { runDatabaseMigrations as runMigration; }
public function runDatabaseMigrations()
{
$this->app->useDatabasePath(base_path('tests/database')); //example path
// dump($this->app->databasePath());
$this->runMigration();
}
或者您可以在您的 AppService 提供者的 boot
方法中设置:
if (config('app.env') === 'testing') { //Laravel automatically set env to 'testing' when running test
$this->app->useDatabasePath(base_path('tests/database'));
}
迁移将查找 'tests/database' 的子文件夹 "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.
Artisan migrate 有一个路径选项,你必须让你自己的特征具有类似的功能。我在想这样的事情。
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;
});
}
}
RefreshDatabase
trait 有一个名为 migrateUsing
的方法,它会重载它在 运行 迁移时使用的参数。我将单个测试的特定测试迁移文件作为 --path
参数传递给迁移。
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;
}