
Utilizando el contenedor de inyección de dependencias de Symfony y PHPUnit para hacer pruebas en Drupal
Tabla de contenido

Hace algún tiempo, trabajamos en un proyecto que utilizaba Drupal 7, el cual, entre otros requisitos, demandaba pruebas automáticas para demostrar la funcionalidad del sistema. Drupal viene con un módulo de pruebas integrado llamado SimpleTest. Sin embargo, al utilizarlo nos dimos cuenta de que no sería suficiente para satisfacer los requerimientos del proyecto.
El Problema
El código fuente de Drupal 7 está basado en procedimientos, lo que significa que no está orientado a objetos. El estilo de programación conocido como "Drupal Way" también sigue este patrón, lo cual genera dificultades para realizar pruebas unitarias. Esto se debe a que las funciones en Drupal 7 están estrechamente interconectadas, lo que hace que sea complicado probarlas de manera aislada.
Nuestra Solución
Para resolver el problema, decidimos adoptar tres enfoques clave:
- Trabajar con código orientado a objetos dentro de los hooks de Drupal.
- Usar un contenedor de inyección de dependencias para gestionar los servicios requeridos por nuestros objetos.
- Usar PHPUnit para las pruebas, debido a su estabilidad y popularidad.
¿Por qué PHPUnit?
Decidimos usar PHPUnit por varias razones:
- Es una herramienta estable, robusta, popular y bien documentada.
- Drupal 8 también utiliza PHPUnit para sus pruebas unitarias, lo que la hace compatible con versiones más recientes de Drupal.
Cambio hacia la Programación Orientada a Objetos
Para realizar pruebas unitarias, necesitábamos cambiar la arquitectura del código. La programación orientada a objetos es ideal para encapsular funcionalidad en objetos que se puedan probar de manera discreta. A continuación, mostramos cómo hicimos este cambio.
Ejemplo Original (función sin orientación a objetos):
Este enfoque depende directamente de Guzzle para hacer la solicitud. Para aplicar programación orientada a objetos, transformamos esta función en un objeto:
Versión Orientada a Objetos:
Y luego reescribimos la función original para usar este objeto:
Pruebas Unitarias con PHPUnit
Una de las ventajas de este enfoque es que ahora podemos escribir pruebas unitarias para verificar el comportamiento del objeto Owner. Aquí mostramos un ejemplo de cómo hacerlo:
Simulando Dependencias con Mocks
En este punto, nos enfrentamos a una nueva cuestión: la función getPropertyList depende de una conexión remota a través de Guzzle. Pero, ¿qué pasa si no podemos o no queremos usar esa conexión para las pruebas unitarias automáticas? La solución es usar mocks para simular la conexión.

Usando Mocks de Guzzle:
Inyectamos una conexión mock en el objeto Owner:
Inyección de Dependencias en el Proyecto
Ahora que tenemos las pruebas unitarias funcionando, necesitamos inyectar la conexión Guzzle en el objeto Owner dentro de la aplicación. Aquí entra en juego el contenedor de inyección de dependencias.Optamos por usar el módulo inject, que utiliza el contenedor de Symfony, el cual también es utilizado en Drupal 8. El siguiente código muestra cómo implementamos este contenedor para gestionar dependencias:
Luego, en nuestra función, inyectamos el servicio:
En resumen, nuestra estrategia consistió en utilizar PHPUnit, programación orientada a objetos, y inyección de dependencias para lograr un sistema de pruebas unitarias repetibles y automatizables. Esta solución nos permitió resolver las dificultades de realizar pruebas unitarias en un código orientado a procedimientos, asegurando que nuestro sistema sea más robusto y fácil de mantener.