数据库测试

    你也可以使用 assertDatabaseMissing 辅助函数来断言数据不在此数据库中。

    当然,使用 assertDatabaseHas 方法和其它辅助函数只是为了方便。 你也可以随意使用PHPUnit内置的断言方法来扩充测试。

    生成模型工厂

    创建一个模型工厂, 使用 Artisan 命令 make:factory 来快速创建模型工厂:

    1. php artisan make:factory PostFactory

    这个新的模型工厂将被放置在 database/factories 目录中。

    —model 选项可用于指定当模型工厂被创建时生成模型的名称。这个选项将用给定的模型预填充生成的模型工厂文件 :

    1. php artisan make:factory PostFactory --model=Post

    每次测试后重置数据库是很有用的,这样以前测试的数据不会干扰后续的测试。 RefreshDatabase trait 会采用最优的方法来迁移你的数据库,这取决于你使用的是内存数据库还是传统数据库。在你的测试类引用这个trait,一切将为你处理:

    1. <?php
    2. namespace Tests\Feature;
    3. use Tests\TestCase;
    4. use Illuminate\Foundation\Testing\RefreshDatabase;
    5. use Illuminate\Foundation\Testing\WithoutMiddleware;
    6. class ExampleTest extends TestCase
    7. {
    8. use RefreshDatabase;
    9. /**
    10. * 一个基本功能测试示例
    11. *
    12. * @return void
    13. */
    14. public function testBasicExample()
    15. {
    16. $response = $this->get('/');
    17. // ...
    18. }

    创建模型工厂

    测试时,在运行测试之前常常需要插入一些数据到数据库中。当你创建测试数据时,除了手动设置每个字段的值,Laravel还可以使用 的工厂来设置每个属性的默认值。在开始之前, 你可以先看一下应用程序 database/factories/UserFactory.php 的文件。 开箱即用,这个文件包含一个模型工厂定义:

    1. use Faker\Generator as Faker;
    2. $factory->define(App\User::class, function (Faker $faker) {
    3. return [
    4. 'name' => $faker->name,
    5. 'email' => $faker->unique()->safeEmail,
    6. 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
    7. 'remember_token' => str_random(10),
    8. ];

    在这个模型工厂定义的闭包中,你可以返回模型上所有属性的默认测试值。闭包将接受 PHP 函数库 Faker 的一个实例,它允许你便捷的生成各种随机数据来进行测试。

    工厂状态可以让你任意组合你的模型工厂,仅需要做出适当差异化的修改,就可以达到让模型拥有多种不同的状态。例如, 你的 User 模型中可以修改某个默认属性值来达到标识一种 delinquent 状态。你可以使用 state 方法来进行这种状态转换。对于简单的工厂状态,你可以传入要修改的属性数组:

    1. $factory->state(App\User::class, 'delinquent', [
    2. 'account_status' => 'delinquent',
    3. ]);

    如果你的工厂状态需要计算或者使用 $faker 实例。你可以使用闭包方法来实现状态属性的修改:

    模型工厂定义后,就可以在测试或者是数据库的填充文件中,通过全局的 factory 函数来生成模型实例。因此,先让我们来看看几个模型创建的例子。 首先,我们将使用 make 方法创建模型但不将他们保存至数据库:

    1. public function testDatabase()
    2. {
    3. $user = factory(App\User::class)->make();
    4. // 在测试中使用模型...
    5. }

    你也可以创建一个含有多个模型的集合,或创建一个指定类型的模型:

    1. // 创建三个 App\User 实例...
    2. $users = factory(App\User::class, 3)->make();

    应用模型工厂状态

    你可能需要在你的模型中应用不同的 。 如果你想模型加上多种不同的状态,你只需指定每个你想要添加状态的名称就可以了:

    1. $users = factory(App\User::class, 5)->states('delinquent')->make();
    2. $users = factory(App\User::class, 5)->states('premium', 'delinquent')->make();

    你可以使用 afterMakingafterCreating 两个方法来注册模型工厂回调。示例代码如下:

    1. $factory->afterMaking(App\User::class, function ($user, $faker) {
    2. // ...
    3. });
    4. $factory->afterCreating(App\User::class, function ($user, $faker) {
    5. $user->accounts()->save(factory(App\Account::class)->make());
    6. });
    1. $factory->afterMakingState(App\User::class, 'delinquent', function ($user, $faker) {
    2. // ...
    3. });
    4. $factory->afterCreatingState(App\User::class, 'delinquent', function ($user, $faker) {
    5. // ...

    重写模型属性

    通过给 make 方法传入一个数组,可以重写模型的默认属性值。这样仅替换指定的属性,其他的属性还是由模型工厂默认填充:

    create 方法创建模型实例的同时还调用了把记录写入数据库的 save 方法:

    1. {
    2. // 创建单个 App\User 实例
    3. $user = factory(App\User::class)->create();
    4. // 创建三个 App\User 实例
    5. $users = factory(App\User::class, 3)->create();
    6. // 在测试中使用模型
    7. }

    传一个数组给 create 方法重写模型的属性:

    1. $user = factory(App\User::class)->create([
    2. 'name' => 'Abigail',
    3. ]);

    这个例子,将为模型添加关联。create 方法创建多模型时,返回 Eloquent 实例集合,这样就可以在集合上使用 each 等便利方法:

    1. $users = factory(App\User::class, 3)
    2. ->create()
    3. ->each(function ($u) {
    4. $u->posts()->save(factory(App\Post::class)->make());
    5. });

    关联 & 属性闭包

    模型工厂定义时,也可以使用闭包里的属性来给模型添加关联。比如,创建 Post 实例时,同时创建 User 实例,就可以这样做:

    1. $factory->define(App\Post::class, function ($faker) {
    2. return [
    3. 'title' => $faker->title,
    4. 'content' => $faker->paragraph,
    5. 'user_id' => function () {
    6. return factory(App\User::class)->create()->id;
    7. }
    8. ];
    9. });

    这些闭包接收一个包含工厂属性的数组:

    1. $factory->define(App\Post::class, function ($faker) {
    2. return [
    3. 'title' => $faker->title,
    4. 'content' => $faker->paragraph,
    5. 'user_id' => function () {
    6. return factory(App\User::class)->create()->id;
    7. },
    8. 'user_type' => function (array $post) {
    9. return App\User::find($post['user_id'])->type;
    10. }
    11. ];

    可用的断言方法

    Laravel 为 PHPUnit 测试提供了多个数据库断言方法:

    本文章首发在 网站上。

    本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
    我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。