跳到主要內容

資料庫測試

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

資料庫測試

簡介

Laravel 提供了多種有用的工具和斷言,使測試您的資料庫驅動應用程式變得更加容易。此外,Laravel 模型工廠和種子填充器使使用應用程式的 Eloquent 模型和關聯來建立測試資料庫記錄變得毫不費力。我們將在以下文檔中討論這些強大的功能。

每次測試後重設資料庫

在繼續之前,讓我們討論如何在每次測試後重設資料庫,以便先前測試的資料不會干擾後續測試。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('/');

        // ...
    }
}

Illuminate\Foundation\Testing\RefreshDatabase trait 在您的架構是最新的情況下不會遷移資料庫。相反,它只會在資料庫交易內行執行測試。因此,不使用此 trait 的測試案例添加到資料庫的任何記錄可能仍然存在於資料庫中。

如果您希望完全重設資料庫,可以改用 Illuminate\Foundation\Testing\DatabaseMigrationsIlluminate\Foundation\Testing\DatabaseTruncation trait。但是,這兩個選項都比 RefreshDatabase trait 慢得多。

模型工廠

測試時,您可能需要在執行測試之前向資料庫中插入一些記錄。與其在建立此測試資料時手動指定每個欄位的值,Laravel 允許您使用模型工廠為每個 Eloquent 模型定義一組預設屬性。

有關建立和利用模型工廠來建立模型的更多資訊,請查閱完整的模型工廠文檔。定義好模型工廠後,您可以在測試中利用工廠來建立模型:

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();

    // ...
}

運行種子填充器

如果您希望使用資料庫種子填充器在功能測試期間填充資料庫,可以呼叫 seed 方法。預設情況下,seed 方法將執行 DatabaseSeeder,它應該執行您所有的其他種子填充器。或者,您可以向 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 () {
    // 運行 DatabaseSeeder...
    $this->seed();

    // 運行特定的種子填充器...
    $this->seed(OrderStatusSeeder::class);

    // ...

    // 運行一組特定的種子填充器...
    $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;

    /**
     * 測試建立一個新的訂單。
     */
    public function test_orders_can_be_created(): void
    {
        // 運行 DatabaseSeeder...
        $this->seed();

        // 運行特定的種子填充器...
        $this->seed(OrderStatusSeeder::class);

        // ...

        // 運行一組特定的種子填充器...
        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
            // ...
        ]);
    }
}

或者,您可以指示 Laravel 在每次使用 RefreshDatabase trait 的測試之前自動填充資料庫。您可以透過向基礎測試類別添加 Seed 屬性來實現這一點:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\Attributes\Seed;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

#[Seed]
abstract class TestCase extends BaseTestCase
{
}

當存在 Seed 屬性時,測試將在每次使用 RefreshDatabase trait 的測試之前運行 Database\Seeders\DatabaseSeeder 類別。但是,您可以透過在測試類別上使用 Seeder 屬性來指定應執行的特定種子填充器:

<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Illuminate\Foundation\Testing\Attributes\Seeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

#[Seeder(OrderStatusSeeder::class)]
class OrderTest extends TestCase
{
    use RefreshDatabase;

    // ...
}

可用斷言

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

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 模型已被「軟刪除」:

$this->assertSoftDeleted($user);

assertNotSoftDeleted

assertNotSoftDeleted 方法可用於斷言給定的 Eloquent 模型未被「軟刪除」:

$this->assertNotSoftDeleted($user);

assertModelExists

斷言給定的模型或模型集合存在於資料庫中:

use App\Models\User;

$user = User::factory()->create();

$this->assertModelExists($user);

assertModelMissing

斷言給定的模型或模型集合不存在於資料庫中:

use App\Models\User;

$user = User::factory()->create();

$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount

expectsDatabaseQueryCount 方法可在測試開始時被呼叫,以指定您預期在測試期間運行的資料庫查詢總數。如果實際執行的查詢數量不完全符合此預期,則測試將失敗:

$this->expectsDatabaseQueryCount(5);

// 測試...