資料庫測試
簡介
Laravel 提供了各種有用的工具和斷言,讓測試資料庫驅動的應用程式更加容易。此外,Laravel 模型工廠和填充器可以輕鬆地使用應用程式的 Eloquent 模型和關聯來建立測試資料庫記錄。我們將在以下文件中討論所有這些強大的功能。
每次測試後重置資料庫
在繼續深入之前,讓我們先討論如何在每次測試後重置資料庫,以避免先前測試的資料干擾後續測試。 Laravel 內建的 Illuminate\Foundation\Testing\RefreshDatabase
trait 將為您處理這個問題。只需在您的測試類別中使用此 trait 即可
1<?php 2 3use Illuminate\Foundation\Testing\RefreshDatabase; 4 5uses(RefreshDatabase::class); 6 7test('basic example', function () { 8 $response = $this->get('/'); 9 10 // ...11});
1<?php 2 3namespace Tests\Feature; 4 5use Illuminate\Foundation\Testing\RefreshDatabase; 6use Tests\TestCase; 7 8class ExampleTest extends TestCase 9{10 use RefreshDatabase;11 12 /**13 * A basic functional test example.14 */15 public function test_basic_example(): void16 {17 $response = $this->get('/');18 19 // ...20 }21}
如果您的資料庫結構是最新的,Illuminate\Foundation\Testing\RefreshDatabase
trait 不會遷移您的資料庫。相反地,它只會在資料庫交易中執行測試。因此,未使用此 trait 的測試案例新增到資料庫的任何記錄可能仍然存在於資料庫中。
如果您想要完全重置資料庫,您可以改用 Illuminate\Foundation\Testing\DatabaseMigrations
或 Illuminate\Foundation\Testing\DatabaseTruncation
trait。然而,這兩個選項都比 RefreshDatabase
trait 慢得多。
模型工廠
在測試時,您可能需要在執行測試之前將一些記錄插入到資料庫中。Laravel 允許您為每個 Eloquent 模型 使用 模型工廠 定義一組預設屬性,而不是在建立此測試資料時手動指定每個欄位的值。
要了解更多關於建立和使用模型工廠來建立模型,請查閱完整的模型工廠文件。一旦您定義了模型工廠,您就可以在測試中使用該工廠來建立模型
1use App\Models\User;2 3test('models can be instantiated', function () {4 $user = User::factory()->create();5 6 // ...7});
1use App\Models\User;2 3public function test_models_can_be_instantiated(): void4{5 $user = User::factory()->create();6 7 // ...8}
執行填充器
如果您想在功能測試期間使用資料庫填充器來填充您的資料庫,您可以調用 seed
方法。預設情況下,seed
方法將執行 DatabaseSeeder
,它應該執行您的所有其他填充器。或者,您可以將特定的填充器類別名稱傳遞給 seed
方法
1<?php 2 3use Database\Seeders\OrderStatusSeeder; 4use Database\Seeders\TransactionStatusSeeder; 5use Illuminate\Foundation\Testing\RefreshDatabase; 6 7uses(RefreshDatabase::class); 8 9test('orders can be created', function () {10 // Run the DatabaseSeeder...11 $this->seed();12 13 // Run a specific seeder...14 $this->seed(OrderStatusSeeder::class);15 16 // ...17 18 // Run an array of specific seeders...19 $this->seed([20 OrderStatusSeeder::class,21 TransactionStatusSeeder::class,22 // ...23 ]);24});
1<?php 2 3namespace Tests\Feature; 4 5use Database\Seeders\OrderStatusSeeder; 6use Database\Seeders\TransactionStatusSeeder; 7use Illuminate\Foundation\Testing\RefreshDatabase; 8use Tests\TestCase; 9 10class ExampleTest extends TestCase11{12 use RefreshDatabase;13 14 /**15 * Test creating a new order.16 */17 public function test_orders_can_be_created(): void18 {19 // Run the DatabaseSeeder...20 $this->seed();21 22 // Run a specific seeder...23 $this->seed(OrderStatusSeeder::class);24 25 // ...26 27 // Run an array of specific seeders...28 $this->seed([29 OrderStatusSeeder::class,30 TransactionStatusSeeder::class,31 // ...32 ]);33 }34}
或者,您可以指示 Laravel 在每個使用 RefreshDatabase
trait 的測試之前自動填充資料庫。您可以通過在您的基本測試類別上定義 $seed
屬性來完成此操作
1<?php 2 3namespace Tests; 4 5use Illuminate\Foundation\Testing\TestCase as BaseTestCase; 6 7abstract class TestCase extends BaseTestCase 8{ 9 /**10 * Indicates whether the default seeder should run before each test.11 *12 * @var bool13 */14 protected $seed = true;15}
當 $seed
屬性為 true
時,測試將在每個使用 RefreshDatabase
trait 的測試之前執行 Database\Seeders\DatabaseSeeder
類別。但是,您可以通過在測試類別上定義 $seeder
屬性來指定應執行的特定填充器
1use Database\Seeders\OrderStatusSeeder;2 3/**4 * Run a specific seeder before each test.5 *6 * @var string7 */8protected $seeder = OrderStatusSeeder::class;
可用的斷言
Laravel 為您的 Pest 或 PHPUnit 功能測試提供了幾個資料庫斷言。我們將在下面討論每個斷言。
assertDatabaseCount
斷言資料庫中的表格包含給定數量的記錄
1$this->assertDatabaseCount('users', 5);
assertDatabaseEmpty
斷言資料庫中的表格不包含任何記錄
1$this->assertDatabaseEmpty('users');
assertDatabaseHas
斷言資料庫中的表格包含符合給定的鍵 / 值查詢約束條件的記錄
1$this->assertDatabaseHas('users', [3]);
assertDatabaseMissing
斷言資料庫中的表格不包含符合給定的鍵 / 值查詢約束條件的記錄
1$this->assertDatabaseMissing('users', [3]);
assertSoftDeleted
assertSoftDeleted
方法可以用於斷言給定的 Eloquent 模型已被「軟刪除」
1$this->assertSoftDeleted($user);
assertNotSoftDeleted
assertNotSoftDeleted
方法可以用於斷言給定的 Eloquent 模型尚未被「軟刪除」
1$this->assertNotSoftDeleted($user);
assertModelExists
斷言給定的模型存在於資料庫中
1use App\Models\User;2 3$user = User::factory()->create();4 5$this->assertModelExists($user);
assertModelMissing
斷言給定的模型不存在於資料庫中
1use App\Models\User;2 3$user = User::factory()->create();4 5$user->delete();6 7$this->assertModelMissing($user);
expectsDatabaseQueryCount
可以在測試開始時調用 expectsDatabaseQueryCount
方法,以指定您預期在測試期間運行的資料庫查詢總數。如果實際執行的查詢數量與此預期不完全相符,則測試將失敗
1$this->expectsDatabaseQueryCount(5);2 3// Test...