跳转到主要内容

简介

Laravel 内置了一整套用来安全、高效地测试与数据库相关功能的机制。将数据库重置 trait、模型工厂、Seeder 与专用断言组合起来,可以让测试更加健壮、不易出错。 首先建议使用 RefreshDatabase。它在大部分场景下都能兼顾测试独立性与执行速度,比完全重建数据库要快得多。

每个测试执行后重置数据库

为了避免上一次测试的数据影响下一次测试,可以使用 Laravel 提供的数据库重置 trait。
<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('基本示例', function () {
    $response = $this->get('/');

    $response->assertOk();
});
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    public function test_basic_example(): void
    {
        $response = $this->get('/');

        $response->assertOk();
    }
}
RefreshDatabase 会判断数据库结构是否为最新版本。如果是最新的,就使用事务运行测试;否则会先执行迁移。 如果不使用事务方式,希望每次都完全重置,可以使用以下 trait。
Trait行为使用场景
RefreshDatabase结构最新时用事务,仅在必要时执行迁移通常首选
DatabaseMigrations每个测试都执行一次迁移需要每次都走完整的迁移生命周期
DatabaseTruncation通过 TRUNCATE 表来初始化不适合用事务的环境下需要彻底清空数据

模型工厂

在测试前准备数据时,使用模型工厂可以简洁地生成 Eloquent 模型。 工厂的定义、state 和关联关系细节请参考 Eloquent 工厂
<?php

use App\Models\User;

test('可以创建模型', function () {
    $user = User::factory()->create();

    expect($user->exists)->toBeTrue();
});
<?php

namespace Tests\Feature;

use App\Models\User;
use Tests\TestCase;

class UserFactoryTest extends TestCase
{
    public function test_models_can_be_instantiated(): void
    {
        $user = User::factory()->create();

        $this->assertTrue($user->exists);
    }
}

执行 Seeder

如果需要在测试中填充数据,可以使用 seed()。不带参数时会运行 DatabaseSeeder,带参数时可以运行指定的 Seeder(或数组)。
<?php

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('可以创建订单', function () {
    $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 OrderTest extends TestCase
{
    use RefreshDatabase;

    public function test_orders_can_be_created(): void
    {
        $this->seed();

        $this->seed(OrderStatusSeeder::class);

        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
        ]);

        // ...
    }
}
如果希望所有使用 RefreshDatabase 的测试都自动执行 seed,可以在基类测试上添加 #[Seed] 属性。
<?php

namespace Tests;

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

#[Seed]
abstract class TestCase extends BaseTestCase
{
}
如果只想自动执行特定的 Seeder,可以使用 #[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 OrderStatusTest extends TestCase
{
    use RefreshDatabase;
}

可用的断言

Laravel 提供了一系列数据库相关的断言,Pest 与 PHPUnit 都可以使用。

assertDatabaseCount

断言表中的记录数与期望值一致。
$this->assertDatabaseCount('users', 5);
$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

断言表为空。
$this->assertDatabaseEmpty('users');
$this->assertDatabaseEmpty('users');

assertDatabaseHas

断言存在与指定条件匹配的记录。
$this->assertDatabaseHas('users', [
    'email' => '[email protected]',
]);
$this->assertDatabaseHas('users', [
    'email' => '[email protected]',
]);

assertDatabaseMissing

断言不存在与指定条件匹配的记录。
$this->assertDatabaseMissing('users', [
    'email' => '[email protected]',
]);
$this->assertDatabaseMissing('users', [
    'email' => '[email protected]',
]);

assertSoftDeleted

断言给定的 Eloquent 模型已被软删除。
$this->assertSoftDeleted($user);
$this->assertSoftDeleted($user);

assertNotSoftDeleted

断言给定的 Eloquent 模型未被软删除。
$this->assertNotSoftDeleted($user);
$this->assertNotSoftDeleted($user);

assertModelExists

断言指定的模型(或模型集合)存在于数据库中。
<?php

use App\Models\User;

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

$this->assertModelExists($user);
<?php

use App\Models\User;

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

$this->assertModelExists($user);

assertModelMissing

断言指定的模型(或模型集合)不存在于数据库中。
<?php

use App\Models\User;

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

$this->assertModelMissing($user);
<?php

use App\Models\User;

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

$this->assertModelMissing($user);

expectsDatabaseQueryCount

在测试开始时严格指定即将执行的数据库查询总数。当实际执行次数与之不一致时测试会失败。
$this->expectsDatabaseQueryCount(5);

// Test...
$this->expectsDatabaseQueryCount(5);

// Test...
最后修改于 2026年7月13日