Lzh on GitHub

数据库测试

简介

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('/');
 
    // ...
});

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();
 
    // ...
});

运行填充器

如果您想在功能测试期间使用 数据库填充器 来填充数据库,您可以调用 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,
        // ...
    ]);
});

或者,您可以指示 Laravel 在每次使用 RefreshDatabase trait 的测试之前自动填充数据库。您可以通过在您的基础测试类上定义一个 $seed 属性来完成此操作:

<?php
 
namespace Tests;
 
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 
abstract class TestCase extends BaseTestCase
{
    /**
     * 指示默认填充器是否应在每次测试前运行。
     *
     * @var bool
     */
    protected $seed = true;
}

$seed 属性为 true 时,测试将在每次使用 RefreshDatabase trait 的测试之前运行 Database\Seeders\DatabaseSeeder 类。但是,您可以通过在测试类上定义一个 $seeder 属性来指定应该执行的特定填充器:

use Database\Seeders\OrderStatusSeeder;
 
/**
 * 在每次测试前运行特定的填充器。
 *
 * @var string
 */
protected $seeder = OrderStatusSeeder::class;

可用断言

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);
 
// 测试...