Laravel Laravel
  • Prologue

    • Release Notes
    • Upgrade Guide
    • Contribution Guide
    • API Documentation
  • Getting Started

    • Installation
    • Configuration
    • Directory Structure
    • Request Lifecycle
  • Dev Environments

    • Homestead
    • Valet
  • Core Concepts

    • Service Container
    • Service Providers
    • Facades
    • Contracts
  • The HTTP Layer

    • Routing
    • Middleware
    • CSRF Protection
    • Controllers
    • Requests
    • Responses
    • Session
    • Validation
  • Views & Templates

    • Views
    • Blade Templates
    • Localization
  • JavaScript & CSS

    • Getting Started
    • Compiling Assets
  • Security

    • Authentication
    • Authorization
    • Password Reset
    • API Authentication
    • Encryption
    • Hashing
  • General Topics

    • Broadcasting
    • Cache
    • Errors & Logging
    • Events
    • File Storage
    • Mail
    • Notifications
    • Queues
  • Database

    • Getting Started
    • Query Builder
    • Pagination
    • Migrations
    • Seeding
    • Redis
  • Eloquent ORM

    • Getting Started
    • Relationships
    • Collections
    • Mutators
    • Serialization
  • Artisan Console

    • Commands
    • Task Scheduling
  • Testing

    • Getting Started
    • Application Testing
    • Database
    • Mocking
  • Official Packages

    • Cashier
    • Envoy
    • Passport
    • Scout
    • Socialite
  • Appendix

    • Collections
    • Helpers
    • Packages
Icon

WARNING You're browsing the documentation for an old version of Laravel. Consider upgrading your project to Laravel 11.x.

Database Testing

  • Introduction
  • Resetting The Database After Each Test
    • Using Migrations
    • Using Transactions
  • Writing Factories
    • Factory States
  • Using Factories
    • Creating Models
    • Persisting Models
    • Relationships

Introduction

Laravel provides a variety of helpful tools to make it easier to test your database driven applications. First, you may use the seeInDatabase helper to assert that data exists in the database matching a given set of criteria. For example, if you would like to verify that there is a record in the users table with the email value of sally@example.com, you can do the following:

public function testDatabase()
{
    // Make call to application...

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

Of course, the seeInDatabase method and other helpers like it are for convenience. You are free to use any of PHPUnit's built-in assertion methods to supplement your tests.

Resetting The Database After Each Test

It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests.

Using Migrations

One approach to resetting the database state is to rollback the database after each test and migrate it before the next test. Laravel provides a simple DatabaseMigrations trait that will automatically handle this for you. Simply use the trait on your test class and everything will be handled for you:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

Using Transactions

Another approach to resetting the database state is to wrap each test case in a database transaction. Again, Laravel provides a convenient DatabaseTransactions trait that will automatically handle this for you:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

{note} By default, this trait will only wrap the default database connection in a transaction. If your application is using multiple database connections, you should define a $connectionsToTransact property on your test class. This property should be an array of connection names to execute the transactions on.

Writing Factories

When testing, you may need to insert a few records into your database before executing your test. Instead of manually specifying the value of each column when you create this test data, Laravel allows you to define a default set of attributes for each of your Eloquent models using model factories. To get started, take a look at the database/factories/ModelFactory.php file in your application. Out of the box, this file contains one factory definition:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

Within the Closure, which serves as the factory definition, you may return the default test values of all attributes on the model. The Closure will receive an instance of the Faker PHP library, which allows you to conveniently generate various kinds of random data for testing.

Of course, you are free to add your own additional factories to the ModelFactory.php file. You may also create additional factory files for each model for better organization. For example, you could create UserFactory.php and CommentFactory.php files within your database/factories directory. All of the files within the factories directory will automatically be loaded by Laravel.

Factory States

States allow you to define discrete modifications that can be applied to your model factories in any combination. For example, your User model might have a delinquent state that modifies one of its default attribute values. You may define your state transformations using the state method:

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

Using Factories

Creating Models

Once you have defined your factories, you may use the global factory function in your tests or seed files to generate model instances. So, let's take a look at a few examples of creating models. First, we'll use the make method to create models but not save them to the database:

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

    // Use model in tests...
}

You may also create a Collection of many models or create models of a given type:

// Create three App\User instances...
$users = factory(App\User::class, 3)->make();

Applying States

You may also apply any of your states to the models. If you would like to apply multiple state transformations to the models, you should specify the name of each state you would like to apply:

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

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

Overriding Attributes

If you would like to override some of the default values of your models, you may pass an array of values to the make method. Only the specified values will be replaced while the rest of the values remain set to their default values as specified by the factory:

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

Persisting Models

The create method not only creates the model instances but also saves them to the database using Eloquent's save method:

public function testDatabase()
{
    // Create a single App\User instance...
    $user = factory(App\User::class)->create();

    // Create three App\User instances...
    $users = factory(App\User::class, 3)->create();

    // Use model in tests...
}

You may override attributes on the model by passing an array to the create method:

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

Relationships

In this example, we'll attach a relation to some created models. When using the create method to create multiple models, an Eloquent collection instance is returned, allowing you to use any of the convenient functions provided by the collection, such as each:

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

Relations & Attribute Closures

You may also attach relationships to models using Closure attributes in your factory definitions. For example, if you would like to create a new User instance when creating a Post, you may do the following:

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

These Closures also receive the evaluated attribute array of the factory that contains them:

$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;
        }
    ];
});
last update:2020-10-15 20:51

成为Laravel合作伙伴

Laravel Partners是提供一流Laravel开发和咨询服务的精英商店。我们每个合作伙伴都可以帮助您制定一个精美,结构完善的项目.

我们的伙伴
Laravel
亮点
  • Our Team
  • 发布说明
  • 入门
  • 路由
  • Blade 模板
  • 身份验证
  • 用户授权
  • Artisan 控制台
  • 数据库
  • Eloquent ORM
  • 测试
资源
  • Laravel Bootcamp
  • Laracasts
  • Laravel News
  • Laracon
  • Laracon EU
  • Laracon India
  • Jobs
  • Forums
  • Trademark
  • 版本发布时间
  • 包开发
  • 命令行应用
  • TALL stack全栈开发
  • Blade UI Kit
  • 前端资源构建
伙伴
  • WebReinvent
  • Vehikl
  • Tighten
  • 64 Robots
  • Active Logic
  • Byte 5
  • Curotec
  • Cyber-Duck
  • DevSquad
  • Jump24
  • Kirschbaum
生态系统
  • Cashier
  • Dusk
  • Echo
  • Envoyer
  • Forge
  • Horizon
  • Nova
  • Octane
  • Sail
  • Sanctum
  • Scout
  • Spark
  • Telescope
  • Valet
  • Vapor

Laravel是一个具有表达力,优雅语法的Web应用程序框架。我们认为,发展必须是一种令人愉悦的创造力,才能真正实现。Laravel试图通过减轻大多数Web项目中使用的常见任务来减轻开发的痛苦.

Laravel是Taylor Otwell的商标.
Copyright © 2011-2025 Laravel中文网 LLC.

  • Twitter
  • GitHub
  • Discord
Laravel 全栈开发网 推荐使用阿里云 按Ctrl+D试试