数据库测试

Laravel 中文文档 · 2019-01-16 10:26:50

简介

Laravel提供了各种有用的工具,可以更轻松地测试数据库驱动的应用程序。 首先, 你可以使用 assertDatabaseHas 辅助函数,来断言数据库中是否存在与指定条件互相匹配的数据。 例如,如果我们想验证 users 数据表中是否存在 email 值为 sally@example.com的数据, 可按如下方式操作:

public function testDatabase()
{
    // 调用应用程序...

    $this->assertDatabaseHas('users', [
        'email' => 'sally@example.com'
    ]);
}

你也可使用 assertDatabaseMissing 辅助函数断言数据库中不存在给定的数据。

当然,assertDatabaseHas 方法和其他类似的帮助函数只是为了方便起见。你还可以随意使用任何PHPUnit的内置断言方法来补充你的测试。

生成模型工厂

使用 make:factory Artisan command命令可以创建一个模型工厂:

php artisan make:factory PostFactory

新生成的工厂位置在 database/factories 目录下:

--model选项用于给工厂创建的模型命名。 此选项将使用给定模型预填充生成的工厂文件:

php artisan make:factory PostFactory --model=Post

每次测试后重置数据库

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

<?php

namespace Tests\Feature;

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

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 一个基本功能测试示例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

创建模型工厂

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

use Faker\Generator as Faker;

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
        'remember_token' => str_random(10),
    ];
});

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

你也可以为每个模型创建一个工厂文件以实现更好的组织。 例如,你可以自database/factories 目录下创建 UserFactory.phpCommentFactory.php 文件。 Laravel将自动加载 factories 目录下的所有文件。

{tip} 你也可以在 config/app.php 配置文件中添加 faker_locale 选项来设置 Faker 的语言环境。

工厂状态

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

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

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

$factory->state(App\User::class, 'address', function ($faker) {
    return [
        'address' => $faker->address,
    ];
});

工厂回调

工厂回调是使用 afterMakingafterCreating 方法注册的,并且允许你在创建模型之后执行其他任务。例如,可以使用回调将附加模型与创建的模型相关联:

$factory->afterMaking(App\User::class, function ($user, $faker) {
    // ...
});

$factory->afterCreating(App\User::class, function ($user, $faker) {
    $user->accounts()->save(factory(App\Account::class)->make());
});

你还可以为 工厂状态 定义回调:

$factory->afterMakingState(App\User::class, 'delinquent', function ($user, $faker) {
    // ...
});

$factory->afterCreatingState(App\User::class, 'delinquent', function ($user, $faker) {
    // ...
});

使用模型工厂

创建模型

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

public function testDatabase()
{
    $user = factory(App\User::class)->make();

    // 在测试中使用模型...
}

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

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

应用状态

你也可将任何状态应用于模型。若将多个状态转换应用于模型,你应当为每个状态指定名称:

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

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

覆盖属性

如果要覆盖模型的某些默认值,你可以将一组值传递给make方法。 这样的话只有指定的值才会被替换,而其余值仍为工厂指定的默认值:

$user = factory(App\User::class)->make([
    'name' => 'Abigail',
]);

持久化模型

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

public function testDatabase()
{
    //  创建单个 App\User 实例...
    $user = factory(App\User::class)->create();

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

    // 在测试中使用模型...
}

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

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

关联

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

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

关联 & 属性闭包

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

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});

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

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'user_type' => function (array $post) {
            return App\User::find($post['user_id'])->type;
        }
    ];
});

可用的断言方法

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

方法 描述
$this->assertDatabaseHas($table, array $data); 断言数据库表中包含给定的数据。
$this->assertDatabaseMissing($table, array $data); 断言数据库表中不包含给定的数据。
$this->assertSoftDeleted($table, array $data); 断言数据库中的指定记录已软删除。

点击查看所有 Laravel 中文文档 文章: https://www.codercto.com/courses/l/3.html

查看所有标签

Writing Windows VxDs and Device Drivers, Second Edition

Writing Windows VxDs and Device Drivers, Second Edition

Karen Hazzah / CMP / 1996-01-12 / USD 54.95

Software developer and author Karen Hazzah expands her original treatise on device drivers in the second edition of "Writing Windows VxDs and Device Drivers." The book and companion disk include the a......一起来看看 《Writing Windows VxDs and Device Drivers, Second Edition》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具