Nuevo en Symfony 4.1: Simplificado el uso de servicios en tests

En Symfony 3.4 hicimos que todos los servicios fueran privados por defecto, de manera que ya no puedes realizar llamadas como $this->get('mi_servicio') dentro de un controlador para obtener un servicio.

Tomamos esta decisión porque usar el contenedor de servicios directamente no es una buena práctica que queramos promover. El principal motivo es que oculta las dependencias de tus clases, haciendo que estén más acopladas y dificultando los tests.

Siempre que eliminamos una funcionalidad como esta, intentamos ofrecer una alternativa que sea mejor y en lo posible, tan fácil o más de usar que la anterior. Por eso ahora en los controladores puedes inyectar servicios en los argumentos de sus acciones y constructores.

El único problema que quedaba es que los tests ahora eran más complicados que antes. De hecho, algunos programadores/as definían una configuración en el entorno test para hacer todos los servicios públicos en los tests. En Symfony 4.1 hemos decidido aplicar la misma idea y podrás por defecto acceder a los servicios privados dentro de los tests.

En la práctica, los tests basados en WebTestCase y KernelTestCase ahora pueden acceder a un contenedor especial mediante la propiedad static::$container que permite acceder a los servicios privados:

use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Console\Tester\CommandTester;
 
class AddUserCommandTest extends WebTestCase
{
    private function assertUserCreated()
    {
        self::bootKernel();
 
        // este es el contendor original sin ningún cambio
        $container = self::$kernel->getContainer();
 
        // este es el contenedor especial que permite acceder a servicios privados
        $client = self::createClient();
 
        $user = self::$container->get('doctrine')->getRepository(User::class)->findOneByEmail('...');
        $this->assertTrue(self::$container->get('security.password_encoder')->isPasswordValid($user, '...');
        // ...
}

Algo a tener en cuenta es que, debido a cómo funciona el contenedor de sevicios de Symfony, lo servicios que no se usan se eliminan del contenedor. Esto significa que si tienes un servicio privado que no se usa en ningún otro servicio, Symfony lo eliminará y no podrás acceder a el tal y como se explica en este artículo. La solución es definit el servicio como public explícitamente para que Symfony no lo elimine.


Esta funcionalidad fue contribuida por Nicolas Grekas en el pull request #26499.

Fuente: New in Symfony 4.1: Simpler service testing

Comentarios

Publicada el

20 de abril de 2018

Etiquetas

Proyectos Symfony destacados

La forma más sencilla de generar el backend de tus aplicaciones Symfony. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.