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('/');
// ...
}
}The Illuminate\Foundation\Testing\RefreshDatabase trait does not migrate your database if your schema is up to date. Instead, it will only execute the test within a database transaction. Therefore, any records added to the database by test cases that do not use this trait may still exist in the database.
如果您想完全重置数据库,您可以使用 Illuminate\Foundation\Testing\DatabaseMigrations 或 Illuminate\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 () {
// Run the DatabaseSeeder...
$this->seed();
// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);
// ...
// Run an array of specific seeders...
$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;
/**
* Test creating a new order.
*/
public function test_orders_can_be_created(): void
{
// Run the DatabaseSeeder...
$this->seed();
// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);
// ...
// Run an array of specific seeders...
$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
{
/**
* Indicates whether the default seeder should run before each test.
*
* @var bool
*/
protected $seed = true;
}当 $seed 属性为 true 时,测试将在每个使用 RefreshDatabase trait 的测试之前运行 Database\Seeders\DatabaseSeeder 类。但是,您可以通过在测试类上定义一个 $seeder 属性来指定一个应该被执行的特定 seeder:
use Database\Seeders\OrderStatusSeeder;
/**
* Run a specific seeder before each test.
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;Laravel 为您的 Pest 或 PHPUnit 功能测试提供了多个数据库断言。 我们将在下面讨论每个断言。
断言数据库中的一个表包含给定数量的记录:
$this->assertDatabaseCount('users', 5);断言数据库中的表不包含任何记录:
$this->assertDatabaseEmpty('users');断言数据库中的一个表包含与给定键/值查询约束匹配的记录:
$this->assertDatabaseHas('users', [
'email' => 'sally@example.com',
]);断言数据库中的表不包含与给定键/值查询约束匹配的记录:
$this->assertDatabaseMissing('users', [
'email' => 'sally@example.com',
]);该 assertSoftDeleted 方法可用于断言给定的 Eloquent 模型已被“软删除”:
$this->assertSoftDeleted($user);assertNotSoftDeleted 方法可用于断言给定 Eloquent 模型未被“软删除”:
$this->assertNotSoftDeleted($user);断言给定的模型或模型集合在数据库中存在:
use App\Models\User;
$user = User::factory()->create();
$this->assertModelExists($user);断言给定模型或模型集合在数据库中不存在:
use App\Models\User;
$user = User::factory()->create();
$user->delete();
$this->assertModelMissing($user);expectsDatabaseQueryCount 方法可以在测试开始时调用,以指定您期望在测试期间运行的数据库查询的总数。如果实际执行的查询数量与此期望不完全匹配,测试将失败:
$this->expectsDatabaseQueryCount(5);
// Test...