介紹 (Introduction)
Laravel 提供了各種有用的工具和斷言,讓測試資料庫驅動的應用程式變得更加容易。此外,Laravel 的 model factories 和 seeders 可以輕鬆地使用你應用程式的 Eloquent models 和關聯來建立測試資料庫記錄。我們會在以下文件中討論所有這些強大的功能。
每次測試後重置資料庫 (Resetting The Database After Each Test)
在繼續之前,讓我們討論如何在每次測試後重置你的資料庫,以便前一次測試的資料不會干擾後續的測試。Laravel 內建的 Illuminate\Foundation\Testing\RefreshDatabase trait 會為你處理這件事。只需在你的測試類別中使用這個 trait:
<?php
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()->use(RefreshDatabase::class);
test('basic example', function () {
$response = $this->get('/');
// ...
});
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
$response = $this->get('/');
// ...
}
}
如果你的 schema 已經是最新的,Illuminate\Foundation\Testing\RefreshDatabase trait 不會遷移你的資料庫。相反地,它只會在資料庫事務中執行測試。因此,由不使用此 trait 的測試案例新增到資料庫的任何記錄可能仍然存在於資料庫中。
如果你想要完全重置資料庫,你可以改用 Illuminate\Foundation\Testing\DatabaseMigrations 或 Illuminate\Foundation\Testing\DatabaseTruncation traits。然而,這兩個選項都比 RefreshDatabase trait 慢很多。
Model Factories
在測試時,你可能需要在執行測試之前將一些記錄插入到你的資料庫中。與其在建立這些測試資料時手動指定每個欄位的值,Laravel 允許你使用 model factories 為每個 Eloquent models 定義一組預設屬性。
要了解更多關於建立和使用 model factories 來建立 models 的資訊,請參閱完整的 model factory 文件。一旦你定義了 model factory,你可以在測試中使用該 factory 來建立 models:
use App\Models\User;
test('models can be instantiated', function () {
$user = User::factory()->create();
// ...
});
use App\Models\User;
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
// ...
}
執行 Seeders (Running Seeders)
如果你想在功能測試期間使用資料庫 seeders 來填充你的資料庫,你可以調用 seed 方法。預設情況下,seed 方法會執行 DatabaseSeeder,它應該會執行你所有其他的 seeders。或者,你可以將特定的 seeder 類別名稱傳遞給 seed 方法:
<?php
use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()->use(RefreshDatabase::class);
test('orders can be created', function () {
// Run the DatabaseSeeder...
$this->seed();
// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);
// ...
// Run an array of specific seeders...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
});
<?php
namespace Tests\Feature;
use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
/**
* Test creating a new order.
*/
public function test_orders_can_be_created(): void
{
// Run the DatabaseSeeder...
$this->seed();
// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);
// ...
// Run an array of specific seeders...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
}
}
或者,你可以指示 Laravel 在使用 RefreshDatabase trait 的每個測試之前自動對資料庫進行 seeding。你可以透過在基礎測試類別上定義 $seed 屬性來完成此操作:
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
/**
* Indicates whether the default seeder should run before each test.
*
* @var bool
*/
protected $seed = true;
}
當 $seed 屬性為 true 時,測試會在使用 RefreshDatabase trait 的每個測試之前執行 Database\Seeders\DatabaseSeeder 類別。然而,你可以透過在測試類別上定義 $seeder 屬性來指定應該執行的特定 seeder:
use Database\Seeders\OrderStatusSeeder;
/**
* Run a specific seeder before each test.
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;
可用的斷言 (Available Assertions)
Laravel 為你的 Pest 或 PHPUnit 功能測試提供了多種資料庫斷言。我們將在下面討論每一個斷言。
assertDatabaseCount
斷言資料庫中的表格包含指定數量的記錄:
$this->assertDatabaseCount('users', 5);
assertDatabaseEmpty
斷言資料庫中的表格不包含任何記錄:
$this->assertDatabaseEmpty('users');
assertDatabaseHas
斷言資料庫中的表格包含符合指定鍵 / 值查詢條件的記錄:
$this->assertDatabaseHas('users', [
'email' => 'sally@example.com',
]);
assertDatabaseMissing
斷言資料庫中的表格不包含符合指定鍵 / 值查詢條件的記錄:
$this->assertDatabaseMissing('users', [
'email' => 'sally@example.com',
]);
assertSoftDeleted
assertSoftDeleted 方法可用於斷言指定的 Eloquent model 已被「軟刪除」:
$this->assertSoftDeleted($user);
assertNotSoftDeleted
assertNotSoftDeleted 方法可用於斷言指定的 Eloquent model 尚未被「軟刪除」:
$this->assertNotSoftDeleted($user);
assertModelExists
斷言指定的 model 或 models 集合存在於資料庫中:
use App\Models\User;
$user = User::factory()->create();
$this->assertModelExists($user);
assertModelMissing
斷言指定的 model 或 models 集合不存在於資料庫中:
use App\Models\User;
$user = User::factory()->create();
$user->delete();
$this->assertModelMissing($user);
expectsDatabaseQueryCount
expectsDatabaseQueryCount 方法可在測試開始時調用,用於指定你預期在測試期間執行的資料庫查詢總數。如果實際執行的查詢數量與此預期不完全相符,測試將會失敗:
$this->expectsDatabaseQueryCount(5);
// Test...