Frameworks de Mock de Objetos para Pruebas Unitarias

Cuando estamos realizando pruebas unitarias sobre nuestro código muchas veces es complicado (si no imposible) realizar pruebas de métodos que interactúan con componentes de terceros o que requieren de la existencia de cierta información que no se dispone en la prueba. Este tipo de problemática, bastante común en el desarrollo de pruebas unitarias, se resuelve con herramientas que permiten simular una funcionalidad o sobrescribir un comportamiento existente. Estos objetos simulados (mock) pueden implementarse utilizando diferentes librerías las cuales cada una de ellas tiene sus ventajas y desventajas.

En este pequeño artículo veremos algunas de estas librerías (con las que he trabajado) y analizaremos sus ventajas y desventajas desde un punto de vista del uso de las mismas, sin entrar en detalles del marco teórico que las encuadran.

Existen muchas herramientas en el mercado para realizar mock de clases y métodos, no voy a entrar en detalles sobre cada una de las funcionalides de estos frameworks, ni en comparaciones detalladas de los mismos, ya que hay extensos artículos en internet que resaltan las bondades de cada uno de ellos, así que solo me limitaré a dar una descripción rápida de las mismas y mi opinión al respecto, resaltando sus características (buenas o malas) luego de haberlos utilizados en distintos proyectos.

En este artículo solo expondré aquellas con las que he trabajado, y estas son PHPUnit, Mockery y AspectMock. La idea es podes mostrar una comparación simple de como escribir la misma acción en los diferentes frameworks y poder comprar las ventajas y desventajas de cada uno de ellos.

El Básico

Dentro del ámbito de las pruebas unitarias el framework PHPUnit es por lejos el más utilizado por todos, el cual implementa todas las funcionalidades para desarrollar de forma eficiente las pruebas requeridas. Este framework incluye los componentes que permite realizar un mock de clases y métodos, que si bien tiene la mayoría de las funcionalidades necesarias muchas veces es un poco tedioso escribir las mismas.

A continuación veremos en detalle cómo simular un conjunto de métodos de una clase:

$mock= $this->getMock('Logger');
$mock->expects($this->once())
     ->method('addInfo')
     ->with($this->equalTo('bar'))
     ->will($this->returnValue(true));

Este ejemplo sencillo simula el método addInfo de la clase Logger, validando que se llame una sola vez, recibiendo por parámetro ‘bar‘, y devolverá true como resultado.

Pros de usar mocks de PHPUnit:
+ No se necesita ninguna librería externa, ya que viene incluida en PHPUnit
+ Extensa y detallada documentación
Contras:
– Sintaxis engorrosa
– No cubre todas las funcionalidades necesarias

El Simple

PHPUnit puede tornarse engorroso cuando se quieren realizar mocks complejos, no es que no se puedan, pero su escritura es compleja y poco práctica de leer. Y para ello sale en nuestra ayuda Mockery, una librería que se aplica sobre un framework de pruebas unitarias (como PHPUnit) y que permite extender y simplificar todo lo relacionado con el “mockeo” (perdón RAE) de objetos y clases. Si bien Mockery tiene una sintaxis muy simple de comprender, dispone de un arsenal de funcionalidades que lo hacen una aliado poderoso a la hora de simular objetos.

El ejemplo anterior podemos expresarlo usando Mockery de la siguiente forma:

$mock = Mockery::mock('Logger');

$mock->shouldReceive('addInfo')
     ->once()
     ->with('bar')
     ->andReturn(true);

Como se puede apreciar, la sintaxis para el mockeo del método es mucho más sencilla y fácil de leer. Esto es un ejemplo muy simple, pero a medida que se hace más complejo lo que se quiere simular (como resultados dinámicos, parámetros dinámicos, o mockeos parciales) se torna mucho más evidente la simplicidad de sintaxis de la cual dispone.

Pros de utilizar Mockery:
+ Sintaxis simple
+ Muchas funcionalidades implementadas de forma muy sencilla
+ Extensa y detallada documentación
Contras:
– Una librería más aparte del framework de prueba unitarias
– No cubre todas las funcionalidades necesarias

El Distinto

AspectMock es un framework muy potente que permite realizar ciertas acciones que a los otros frameworks le cuestan o le son imposibles. Si bien AspectMock no tiene la mayor legibilidad permite realizar el mockeo de cualquier clase, incluyendo las del propio PHP, así como también de funciones sueltas. Además permite mockear clases estáticas, lo cual puede ser de mucha ayuda en ciertos frameworks (como Laravel). En nuestro ejemplo anterior, realizar el mockeo del método addInfo de la clase Logger se debería implementar de la siguiente manera.

use AspectMock\Test as test;

$mock = test::double('Logger',['addInfo' => true]);
$mock->verifyInvokedOnce('addInfo', ['bar']);

Con una sintaxis muy reducida, que en ciertos casos puede volverse un poco compleja de leer, AspectMock es el mejor aliado a la hora de mockear clases y métodos, ya que permite realizar lo mismo que los frameworks anteriores con el agregado de poder simular clases estáticas, funciones del sistema y la posibilidad de implementar TDD de una manera muy simple (ver el excelente artículo publicado por nuestro colega Santiago Murchio para una introducción a esta metodología).

Pros de usar AspectMock:
+ Sintaxis muy simple (al menos en las situaciones básicas)
+ Cubre todas las funcionalidades necesarias
Contras:
– Una librería más aparte del framework de prueba unitarias
– La documentación es muy básica

Conclusiones

Los frameworks para realizar el mock de clases y métodos son herramientas esenciales en el desarrollo de cualquier aplicación que se precie, ya que nos permiten realizar nuestras pruebas aislándonos de componentes que no podemos gestionar (como un componente de terceros), o que tienen un comportamiento no determinístico (como leer información de un dispositivo externo) o el cual no queremos incluir en nuestro test (porque otros tests ya lo prueban).

A mi humilde criterio AspectMock se lleva los laureles por la simplicidad y potencia que nos brinda, así como la capacidad para simular funciones y clases que los otros frameworks no pueden o no lo hacen de forma simple. En segundo lugar dejo Mockery, su simple sintaxis y flexibilidad superan por mucho a lo provisto por PHPUnit, el cual trato de evitar por todos los medios de usar.

Lo bueno de estos frameworks es que no necesitamos casarnos con uno solo de ellos, sino que, como todos los aspectos de la tecnología, podemos utilizar el que mejor se ajuste a nuestras necesidades en cada proyecto.

Tags

Access top talent now!

Related

Get in Touch