1. Pruebas
  2. Pruebas de Bases de Datos

Introducción

Laravel proporciona una variedad de herramientas y asertos útiles para facilitar las pruebas de tus aplicaciones impulsadas por bases de datos. Además, las fábricas y seeders de modelos de Laravel facilitan la creación de registros de prueba en la base de datos utilizando los modelos Eloquent y las relaciones de tu aplicación. Discutiremos todas estas funciones potentes en la siguiente documentación.

Restablecer la base de datos después de cada prueba

Antes de continuar mucho más, veamos cómo restablecer tu base de datos después de cada una de tus pruebas para que los datos de una prueba anterior no interfieran con las pruebas posteriores. El rasgo incluido Illuminate\Foundation\Testing\RefreshDatabase se encargará de esto por ti. Simplemente usa el rasgo en tu clase de prueba:

<?php
 
namespace Tests\Feature;
 
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
use RefreshDatabase;
 
/**
* Un ejemplo básico de prueba funcional.
*/
public function test_basic_example(): void
{
$response = $this->get('/');
 
// ...
}
}

El rasgo Illuminate\Foundation\Testing\RefreshDatabase no migra tu base de datos si tu esquema está actualizado. En cambio, solo ejecutará la prueba dentro de una transacción de base de datos. Por lo tanto, cualquier registro agregado a la base de datos por casos de prueba que no utilicen este rasgo aún puede existir en la base de datos.

Si deseas restablecer por completo la base de datos, puedes utilizar los rasgos Illuminate\Foundation\Testing\DatabaseMigrations o Illuminate\Foundation\Testing\DatabaseTruncation. Sin embargo, ambas opciones son significativamente más lentas que el rasgo RefreshDatabase.

Fábricas de modelos

Al realizar pruebas, es posible que necesites insertar algunos registros en tu base de datos antes de ejecutar tu prueba. En lugar de especificar manualmente el valor de cada columna al crear estos datos de prueba, Laravel te permite definir un conjunto de atributos predeterminados para cada uno de tus modelos Eloquent utilizando fábricas de modelos.

Para obtener más información sobre cómo crear y utilizar fábricas de modelos para crear modelos, consulta la documentación completa de fábricas de modelos. Una vez que hayas definido una fábrica de modelos, puedes utilizarla dentro de tu prueba para crear modelos:

use App\Models\User;
 
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
 
// ...
}

Ejecución de seeders

Si deseas utilizar seeders de bases de datos para poblar tu base de datos durante una prueba de funciones, puedes invocar el método seed. De forma predeterminada, el método seed ejecutará DatabaseSeeder, que debería ejecutar todos tus otros seeders. Alternativamente, puedes pasar un nombre de clase de seeder específico al método seed:

<?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;
 
/**
* Prueba de creación de un nuevo pedido.
*/
public function test_orders_can_be_created(): void
{
// Ejecuta el DatabaseSeeder...
$this->seed();
 
// Ejecuta un seeder específico...
$this->seed(OrderStatusSeeder::class);
 
// ...
 
// Ejecuta un array de seeders específicos...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
}
}

Alternativamente, puedes indicar a Laravel que llene automáticamente la base de datos antes de cada prueba que utiliza el rasgo RefreshDatabase. Puedes lograr esto definiendo una propiedad $seed en tu clase base de prueba:

<?php
 
namespace Tests;
 
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
 
/**
* Indica si el seeder predeterminado debe ejecutarse antes de cada prueba.
*
* @var bool
*/
protected $seed = true;
}

Cuando la propiedad $seed es true, la prueba ejecutará la clase Database\Seeders\DatabaseSeeder antes de cada prueba que utiliza el rasgo RefreshDatabase. Sin embargo, puedes especificar un seeder específico que debe ejecutarse definiendo una propiedad $seeder en tu clase de prueba:

use Database\Seeders\OrderStatusSeeder;
 
/**
* Ejecuta un seeder específico antes de cada prueba.
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;

Asertos disponibles

Laravel proporciona varios asertos de base de datos para tus pruebas de funciones de PHPUnit. Discutiremos cada uno de estos asertos a continuación.

assertDatabaseCount

Asegura que una tabla en la base de datos contenga la cantidad dada de registros:

$this->assertDatabaseCount('users', 5);

assertDatabaseHas

Asegura que una tabla en la base de datos contenga registros que cumplan con las restricciones dadas de consulta clave / valor:

$this->assertDatabaseHas('users', [
'email' => '[email protected]',
]);

assertDatabaseMissing

Asegura que una tabla en la base de datos no contenga registros que cumplan con las restricciones dadas de consulta clave / valor:

$this->assertDatabaseMissing('users', [
'email' => '[email protected]',
]);

assertSoftDeleted

El método assertSoftDeleted se puede usar para afirmar que un modelo Eloquent dado ha sido "soft deleted":

$this->assertSoftDeleted($user);

assertNotSoftDeleted

El método assertNotSoftDeleted se puede usar para afirmar que un modelo Eloquent dado no ha sido "soft deleted":

$this->assertNotSoftDeleted($user);

assertModelExists

Asegura que un modelo dado exista en la base de datos:

use App\Models\User;
 
$user = User::factory()->create();
 
$this->assertModelExists($user);

assertModelMissing

Asegura que un modelo dado no exista en la base de datos:

use App\Models\User;
 
$user = User::factory()->create();
 
$user->delete();
 
$this->assertModelMissing($user);

expectsDatabaseQueryCount

El método expectsDatabaseQueryCount se puede invocar al principio de tu prueba para especificar el número total de consultas de base de datos que esperas que se ejecuten durante la prueba. Si el número real de consultas ejecutadas no coincide exactamente con esta expectativa, la prueba fallará:

$this->expectsDatabaseQueryCount(5);
 
// Prueba...