Init
This commit is contained in:
646
output/12.x/database-testing.md
Normal file
646
output/12.x/database-testing.md
Normal file
@@ -0,0 +1,646 @@
|
||||
# Database Testing
|
||||
|
||||
* Introduction
|
||||
* Resetting the Database After Each Test
|
||||
* Model Factories
|
||||
* Running Seeders
|
||||
* Available Assertions
|
||||
|
||||
## Introduction
|
||||
|
||||
Laravel provides a variety of helpful tools and assertions to make it easier
|
||||
to test your database driven applications. In addition, Laravel model
|
||||
factories and seeders make it painless to create test database records using
|
||||
your application's Eloquent models and relationships. We'll discuss all of
|
||||
these powerful features in the following documentation.
|
||||
|
||||
### Resetting the Database After Each Test
|
||||
|
||||
Before proceeding much further, let's discuss how to reset your database after
|
||||
each of your tests so that data from a previous test does not interfere with
|
||||
subsequent tests. Laravel's included
|
||||
`Illuminate\Foundation\Testing\RefreshDatabase` trait will take care of this
|
||||
for you. Simply use the trait on your test class:
|
||||
|
||||
Pest PHPUnit
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
4
|
||||
|
||||
5pest()->use(RefreshDatabase::class);
|
||||
|
||||
6
|
||||
|
||||
7test('basic example', function () {
|
||||
|
||||
8 $response = $this->get('/');
|
||||
|
||||
9
|
||||
|
||||
10 // ...
|
||||
|
||||
11});
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
pest()->use(RefreshDatabase::class);
|
||||
|
||||
test('basic example', function () {
|
||||
$response = $this->get('/');
|
||||
|
||||
// ...
|
||||
});
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace Tests\Feature;
|
||||
|
||||
4
|
||||
|
||||
5use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
6use Tests\TestCase;
|
||||
|
||||
7
|
||||
|
||||
8class ExampleTest extends TestCase
|
||||
|
||||
9{
|
||||
|
||||
10 use RefreshDatabase;
|
||||
|
||||
11
|
||||
|
||||
12 /**
|
||||
|
||||
13 * A basic functional test example.
|
||||
|
||||
14 */
|
||||
|
||||
15 public function test_basic_example(): void
|
||||
|
||||
16 {
|
||||
|
||||
17 $response = $this->get('/');
|
||||
|
||||
18
|
||||
|
||||
19 // ...
|
||||
|
||||
20 }
|
||||
|
||||
21}
|
||||
|
||||
|
||||
<?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.
|
||||
|
||||
If you would like to totally reset the database, you may use the
|
||||
`Illuminate\Foundation\Testing\DatabaseMigrations` or
|
||||
`Illuminate\Foundation\Testing\DatabaseTruncation` traits instead. However,
|
||||
both of these options are significantly slower than the `RefreshDatabase`
|
||||
trait.
|
||||
|
||||
## Model 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 set of default
|
||||
attributes for each of your [Eloquent models](/docs/12.x/eloquent) using
|
||||
[model factories](/docs/12.x/eloquent-factories).
|
||||
|
||||
To learn more about creating and utilizing model factories to create models,
|
||||
please consult the complete [model factory documentation](/docs/12.x/eloquent-
|
||||
factories). Once you have defined a model factory, you may utilize the factory
|
||||
within your test to create models:
|
||||
|
||||
Pest PHPUnit
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3test('models can be instantiated', function () {
|
||||
|
||||
4 $user = User::factory()->create();
|
||||
|
||||
5
|
||||
|
||||
6 // ...
|
||||
|
||||
7});
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
test('models can be instantiated', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
// ...
|
||||
});
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3public function test_models_can_be_instantiated(): void
|
||||
|
||||
4{
|
||||
|
||||
5 $user = User::factory()->create();
|
||||
|
||||
6
|
||||
|
||||
7 // ...
|
||||
|
||||
8}
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
public function test_models_can_be_instantiated(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
## Running Seeders
|
||||
|
||||
If you would like to use [database seeders](/docs/12.x/seeding) to populate
|
||||
your database during a feature test, you may invoke the `seed` method. By
|
||||
default, the `seed` method will execute the `DatabaseSeeder`, which should
|
||||
execute all of your other seeders. Alternatively, you pass a specific seeder
|
||||
class name to the `seed` method:
|
||||
|
||||
Pest PHPUnit
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3use Database\Seeders\OrderStatusSeeder;
|
||||
|
||||
4use Database\Seeders\TransactionStatusSeeder;
|
||||
|
||||
5use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
6
|
||||
|
||||
7pest()->use(RefreshDatabase::class);
|
||||
|
||||
8
|
||||
|
||||
9test('orders can be created', function () {
|
||||
|
||||
10 // Run the DatabaseSeeder...
|
||||
|
||||
11 $this->seed();
|
||||
|
||||
12
|
||||
|
||||
13 // Run a specific seeder...
|
||||
|
||||
14 $this->seed(OrderStatusSeeder::class);
|
||||
|
||||
15
|
||||
|
||||
16 // ...
|
||||
|
||||
17
|
||||
|
||||
18 // Run an array of specific seeders...
|
||||
|
||||
19 $this->seed([
|
||||
|
||||
20 OrderStatusSeeder::class,
|
||||
|
||||
21 TransactionStatusSeeder::class,
|
||||
|
||||
22 // ...
|
||||
|
||||
23 ]);
|
||||
|
||||
24});
|
||||
|
||||
|
||||
<?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,
|
||||
// ...
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace Tests\Feature;
|
||||
|
||||
4
|
||||
|
||||
5use Database\Seeders\OrderStatusSeeder;
|
||||
|
||||
6use Database\Seeders\TransactionStatusSeeder;
|
||||
|
||||
7use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
8use Tests\TestCase;
|
||||
|
||||
9
|
||||
|
||||
10class ExampleTest extends TestCase
|
||||
|
||||
11{
|
||||
|
||||
12 use RefreshDatabase;
|
||||
|
||||
13
|
||||
|
||||
14 /**
|
||||
|
||||
15 * Test creating a new order.
|
||||
|
||||
16 */
|
||||
|
||||
17 public function test_orders_can_be_created(): void
|
||||
|
||||
18 {
|
||||
|
||||
19 // Run the DatabaseSeeder...
|
||||
|
||||
20 $this->seed();
|
||||
|
||||
21
|
||||
|
||||
22 // Run a specific seeder...
|
||||
|
||||
23 $this->seed(OrderStatusSeeder::class);
|
||||
|
||||
24
|
||||
|
||||
25 // ...
|
||||
|
||||
26
|
||||
|
||||
27 // Run an array of specific seeders...
|
||||
|
||||
28 $this->seed([
|
||||
|
||||
29 OrderStatusSeeder::class,
|
||||
|
||||
30 TransactionStatusSeeder::class,
|
||||
|
||||
31 // ...
|
||||
|
||||
32 ]);
|
||||
|
||||
33 }
|
||||
|
||||
34}
|
||||
|
||||
|
||||
<?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,
|
||||
// ...
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Alternatively, you may instruct Laravel to automatically seed the database
|
||||
before each test that uses the `RefreshDatabase` trait. You may accomplish
|
||||
this by defining a `$seed` property on your base test class:
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace Tests;
|
||||
|
||||
4
|
||||
|
||||
5use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
|
||||
6
|
||||
|
||||
7abstract class TestCase extends BaseTestCase
|
||||
|
||||
8{
|
||||
|
||||
9 /**
|
||||
|
||||
10 * Indicates whether the default seeder should run before each test.
|
||||
|
||||
11 *
|
||||
|
||||
12 * @var bool
|
||||
|
||||
13 */
|
||||
|
||||
14 protected $seed = true;
|
||||
|
||||
15}
|
||||
|
||||
|
||||
<?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;
|
||||
}
|
||||
|
||||
When the `$seed` property is `true`, the test will run the
|
||||
`Database\Seeders\DatabaseSeeder` class before each test that uses the
|
||||
`RefreshDatabase` trait. However, you may specify a specific seeder that
|
||||
should be executed by defining a `$seeder` property on your test class:
|
||||
|
||||
|
||||
|
||||
1use Database\Seeders\OrderStatusSeeder;
|
||||
|
||||
2
|
||||
|
||||
3/**
|
||||
|
||||
4 * Run a specific seeder before each test.
|
||||
|
||||
5 *
|
||||
|
||||
6 * @var string
|
||||
|
||||
7 */
|
||||
|
||||
8protected $seeder = OrderStatusSeeder::class;
|
||||
|
||||
|
||||
use Database\Seeders\OrderStatusSeeder;
|
||||
|
||||
/**
|
||||
* Run a specific seeder before each test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $seeder = OrderStatusSeeder::class;
|
||||
|
||||
## Available Assertions
|
||||
|
||||
Laravel provides several database assertions for your
|
||||
[Pest](https://pestphp.com) or [PHPUnit](https://phpunit.de) feature tests.
|
||||
We'll discuss each of these assertions below.
|
||||
|
||||
#### assertDatabaseCount
|
||||
|
||||
Assert that a table in the database contains the given number of records:
|
||||
|
||||
|
||||
|
||||
1$this->assertDatabaseCount('users', 5);
|
||||
|
||||
|
||||
$this->assertDatabaseCount('users', 5);
|
||||
|
||||
#### assertDatabaseEmpty
|
||||
|
||||
Assert that a table in the database contains no records:
|
||||
|
||||
|
||||
|
||||
1$this->assertDatabaseEmpty('users');
|
||||
|
||||
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
#### assertDatabaseHas
|
||||
|
||||
Assert that a table in the database contains records matching the given key /
|
||||
value query constraints:
|
||||
|
||||
|
||||
|
||||
1$this->assertDatabaseHas('users', [
|
||||
|
||||
2 'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||||
|
||||
3]);
|
||||
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||||
]);
|
||||
|
||||
#### assertDatabaseMissing
|
||||
|
||||
Assert that a table in the database does not contain records matching the
|
||||
given key / value query constraints:
|
||||
|
||||
|
||||
|
||||
1$this->assertDatabaseMissing('users', [
|
||||
|
||||
2 'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||||
|
||||
3]);
|
||||
|
||||
|
||||
$this->assertDatabaseMissing('users', [
|
||||
'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||||
]);
|
||||
|
||||
#### assertSoftDeleted
|
||||
|
||||
The `assertSoftDeleted` method may be used to assert a given Eloquent model
|
||||
has been "soft deleted":
|
||||
|
||||
|
||||
|
||||
1$this->assertSoftDeleted($user);
|
||||
|
||||
|
||||
$this->assertSoftDeleted($user);
|
||||
|
||||
#### assertNotSoftDeleted
|
||||
|
||||
The `assertNotSoftDeleted` method may be used to assert a given Eloquent model
|
||||
hasn't been "soft deleted":
|
||||
|
||||
|
||||
|
||||
1$this->assertNotSoftDeleted($user);
|
||||
|
||||
|
||||
$this->assertNotSoftDeleted($user);
|
||||
|
||||
#### assertModelExists
|
||||
|
||||
Assert that a given model or collection of models exist in the database:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$user = User::factory()->create();
|
||||
|
||||
4
|
||||
|
||||
5$this->assertModelExists($user);
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->assertModelExists($user);
|
||||
|
||||
#### assertModelMissing
|
||||
|
||||
Assert that a given model or collection of models do not exist in the
|
||||
database:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$user = User::factory()->create();
|
||||
|
||||
4
|
||||
|
||||
5$user->delete();
|
||||
|
||||
6
|
||||
|
||||
7$this->assertModelMissing($user);
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
$user->delete();
|
||||
|
||||
$this->assertModelMissing($user);
|
||||
|
||||
#### expectsDatabaseQueryCount
|
||||
|
||||
The `expectsDatabaseQueryCount` method may be invoked at the beginning of your
|
||||
test to specify the total number of database queries that you expect to be run
|
||||
during the test. If the actual number of executed queries does not exactly
|
||||
match this expectation, the test will fail:
|
||||
|
||||
|
||||
|
||||
1$this->expectsDatabaseQueryCount(5);
|
||||
|
||||
2
|
||||
|
||||
3// Test...
|
||||
|
||||
|
||||
$this->expectsDatabaseQueryCount(5);
|
||||
|
||||
// Test...
|
||||
|
||||
Reference in New Issue
Block a user