Buy Access to Course
08.

El ayudante de pruebas del repositorio

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

¡Muy bien, equipo! ¡Hemos cubierto todas las partes principales de las pruebas de integración! ¡Woo! Y es deliciosamente sencillo: sólo una estrategia para coger los servicios reales de un contenedor y probarlos, lo que... en última instancia nos da una prueba más realista.

Los inconvenientes de las pruebas de integración son que se ejecutan más lentamente que las pruebas unitarias, y a menudo son más complejas... porque tenemos que pensar en cosas como limpiar y sembrar la base de datos. Y a veces, no queremos que ocurran cosas reales (como llamadas a la API). En este caso, podemos utilizar un poco de Mocking para evitarlo. La gran conclusión es, como en todo, utilizar la herramienta adecuada -pruebas unitarias o pruebas de integración- para el trabajo adecuado. Eso es situacional y está bien utilizar ambas.

A medida que nos acercamos a la línea de meta, vamos a sumergirnos en las pruebas de algunas de las partes más complicadas de nuestro sistema: por ejemplo, si se enviaron correos electrónicos o mensajes de Messenger. Para ello, tenemos que dar a Bob un nuevo superpoder: la capacidad de bloquear el parque. Una vez activado, nuestra aplicación enviará un correo electrónico al personal del parque, básicamente diciendo:

¡Alerta! ¡Dinosaurios sueltos!

Crear el comando

Dirígete a LockDownHelper. Aquí abajo, crea un nuevo método. Lo llamaremos para bloquear el parque, así que ¿qué te parece public function dinoEscaped(). Dale un tipo de retorno void y pon aquí algunos comentarios TODO que indiquen lo que tenemos que hacer: guardar un LockDown en la base de datos y enviar un correo electrónico.

38 lines | src/Service/LockDownHelper.php
// ... lines 1 - 8
class LockDownHelper
{
// ... lines 11 - 31
public function dinoEscaped(): void
{
// TODO: create a LockDown & save
// send an email with subject like "RUUUUUUNNNNNN!!!!"
}
}

Para llamar a este código y activar el bloqueo, vamos a crear un nuevo comando de consola. En el terminal, ejecuta:

php bin/console make:command

Llámalo app:lockdown:start.

¡Bastante sencillo! Eso ha creado una única clase en src/Command/LockdownStartCommand.php. En su interior, autoconecta un private LockDownHelper $lockDownHelper y asegúrate de llamar al constructor parent.

39 lines | src/Command/LockdownStartCommand.php
// ... lines 1 - 4
use App\Service\LockDownHelper;
// ... lines 6 - 13
#[AsCommand(
name: 'app:lockdown:start',
description: 'Add a short description for your command',
)]
class LockdownStartCommand extends Command
{
public function __construct(private LockDownHelper $lockDownHelper)
{
parent::__construct();
}
// ... lines 24 - 37
}

Aquí abajo, borra casi toda esta lógica... y sustitúyela por$this->lockDownHelper->dinoEscaped() y$io->caution('Lockdown started!!!!!!!!!!').

39 lines | src/Command/LockdownStartCommand.php
// ... lines 1 - 28
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$this->lockDownHelper->dinoEscaped();
$io->caution('Lockdown started!!!!!!');
return Command::SUCCESS;
}
// ... lines 38 - 39

Peligroso. Este método aún no hace nada, pero ya podemos ir probando el comando. Copia su nombre... y ejecútalo:

php bin/console app:lockdown:start

¡Me encanta!

Crear la prueba

Antes de ensuciarnos las manos con el nuevo método, vamos a escribir una prueba. Pero antes, hagamos ese truco en el que añadimos un private function para ayudarnos a obtener el servicio que estamos probando: private function getLockDownHelper() que devolverá unLockDownHelper. Dentro, copia el código de arriba... y devuélvelo. Luego, simplifica el código de aquí arriba a sólo $this->getLockDownHelper()->endCurrentLockDown().

// ... lines 1 - 12
class LockDownHelperTest extends KernelTestCase
{
// ... lines 15 - 16
public function testEndCurrentLockdown()
{
// ... lines 19 - 29
$this->getLockDownHelper()->endCurrentLockDown();
// ... line 31
}
// ... line 33
private function getLockDownHelper(): LockDownHelper
{
return self::getContainer()->get(LockDownHelper::class);
}
}

Muy bien, ahora crea el nuevo método de prueba:public function testDinoEscapedPersistsLockDown(). Empieza como siempre: arrancando el kernel. Luego llama al método con$this->getLockDownHelper()->dinoEscaped().

// ... lines 1 - 33
public function testDinoEscapedPersistsLockDown()
{
self::bootKernel();
$this->getLockDownHelper()->dinoEscaped();
}
// ... lines 40 - 46

¡Genial! No es interesante, pero haz la prueba de todos modos:

symfony php vendor/bin/phpunit tests/Integration/Service/LockDownHelperTest.php

No falla, pero... es arriesgado porque no hemos realizado ninguna aserción.

Aserciones de la base de datos a través del repositorio

Lo que queremos afirmar es que se ha insertado una fila en la base de datos. Para ello, podríamos coger el gestor de entidades o nuestro servicio de repositorio, hacer una consulta y realizar algunas aserciones utilizándolo. Sin embargo, Foundry viene con un buen truco para esto.

Después de llamar al método, digamos LockDownFactory. Normalmente, llamaríamos a cosas comocreate o createMany, pero éste también tiene un método llamado repository. Éste devuelve un objeto de Foundry que envuelve el repositorio -de forma muy parecida a como Foundry envuelve nuestras entidades en un objeto Proxy. Esto significa que podemos llamar a métodos reales del repositorio, como findMostRecent() o isInLockDown(). Pero también tiene cosas extra, como assert(). Digamos ->assert()->count(1) para asegurarnos de que hay un registro en esta tabla. Podríamos ir más allá y obtener ese registro para asegurarnos de que su estado es "activo", pero me lo saltaré.

// ... lines 1 - 33
public function testDinoEscapedPersistsLockDown()
{
// ... lines 36 - 38
LockDownFactory::repository()->assert()->count(1);
}
// ... lines 41 - 47

Ejecuta ahora la prueba.

symfony php vendor/bin/phpunit tests/Integration/Service/LockDownHelperTest.php

Debería fallar y... falla.

Voy a pegar un código que cree el LockDown y lo guarde. Fácil y aburrido código.

43 lines | src/Service/LockDownHelper.php
// ... lines 1 - 9
class LockDownHelper
// ... lines 11 - 32
public function dinoEscaped(): void
{
$lockDown = new LockDown();
$lockDown->setStatus(LockDownStatus::ACTIVE);
$lockDown->setReason('Dino escaped... NOT good...');
$this->entityManager->persist($lockDown);
$this->entityManager->flush();
// send an email with subject like "RUUUUUUNNNNNN!!!!"
}
}

Ejecuta la prueba ahora... ¡pasa!

Siguiente paso: enviemos el correo electrónico y comprobemos que se ha enviado. Lo haremos con algunas herramientas básicas de Symfony y también con otra librería de zenstruck.