跳到內容

資料庫測試

簡介

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(): void
16 {
17 $response = $this->get('/');
18 
19 // ...
20 }
21}

如果您的資料庫結構是最新的,Illuminate\Foundation\Testing\RefreshDatabase trait 不會遷移您的資料庫。相反地,它只會在資料庫交易中執行測試。因此,未使用此 trait 的測試案例新增到資料庫的任何記錄可能仍然存在於資料庫中。

如果您想要完全重置資料庫,您可以改用 Illuminate\Foundation\Testing\DatabaseMigrationsIlluminate\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(): void
4{
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 TestCase
11{
12 use RefreshDatabase;
13 
14 /**
15 * Test creating a new order.
16 */
17 public function test_orders_can_be_created(): void
18 {
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 bool
13 */
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 string
7 */
8protected $seeder = OrderStatusSeeder::class;

可用的斷言

Laravel 為您的 PestPHPUnit 功能測試提供了幾個資料庫斷言。我們將在下面討論每個斷言。

assertDatabaseCount

斷言資料庫中的表格包含給定數量的記錄

1$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

斷言資料庫中的表格不包含任何記錄

1$this->assertDatabaseEmpty('users');

assertDatabaseHas

斷言資料庫中的表格包含符合給定的鍵 / 值查詢約束條件的記錄

1$this->assertDatabaseHas('users', [
2 'email' => '[email protected]',
3]);

assertDatabaseMissing

斷言資料庫中的表格不包含符合給定的鍵 / 值查詢約束條件的記錄

1$this->assertDatabaseMissing('users', [
2 'email' => '[email protected]',
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...

Laravel 是建構最有效率的方式,
建構、部署和監控軟體。