leanmind logo leanmind text logo

Blog

Refactorización Avanzada

Dominar el refactoring productivo para maximizar el retorno de la inversión.

Custom assertions, con AssertJ, para objetos de dominio

Por Raul Padilla y Rubén Zamora

Introducción

Agradecimientos

Especial agradecimiento a Sergio Martínez González, porque fue quien nos enseñó este patrón para poder desbloquear esta necesidad.

¿Por qué hemos necesitado hacer esto?

Trabajábamos con Java 8 y las librerías de acceso a base de datos eran privatizadas y no podíamos realizar test tan fácilmente. En ciertos casos, los hash de los objetos que queríamos comparar, nos decían constantemente que eran diferentes, siendo aparentemente totalmente iguales. Por ejemplo:

org.opentest4j.AssertionFailedError: 
expected: "Employee{id=2, name='Pepe', status='working'} (Employee@6cd7f381)"
 but was: "Employee{id=2, name='Pepe', status='working'} (Employee@4ffe3d42)"

Aquí, vemos un claro ejemplo de un mal feedback sobre la comparación del objeto, siendo los datos iguales pero su hash diferente. Sin tener ninguna idea de por qué hace esto por detrás, lo que planteamos a continuación, es la solución a esta casuística. Para quién quiera ver la clase Employee, la cual tiene implementado el equals y el hashcode, la dejamos por aquí.

Recursos de lectura previa que te pueden ayudar

Entorno

Repositorio GitHub

Solución planteada: Envolver el AssertJ en una clase de afirmación

Lo que tuvimos que hacer, fue crear una clase que funciona como un framework, que nos permite realizar afirmaciones sobre los datos de nuestra entidad, para verificar que son los que esperamos. La hemos llamado EmployeeAssertion.

Para invocarla, nosotros hemos optado por ocultarla en el método privado assertThatEmployeeWithId(), que existe en nuestra clase de apoyo para test de integración DataBaseInMemoryTestSuite. Éste sería un ejemplo que cómo nos quedaría:

Partiendo de una premisa en la que insertamos los siguientes registros en base de datos:

INSERT INTO employees (id, name, status) VALUES (1, 'Manolo', 'working');
INSERT INTO employees (id, name, status) VALUES (2, 'Pepe', 'working');

Realizamos la afirmación de la siguiente manera:

@Test
@DisplayName("Should retrieve an employee by them id")
public void should_retrieve_an_employee_by_them_id() {
    Employee employee = repository.find(2);

    assertThatEmployeeWithId(employee.getId())
      .hasStatus("working")
      .hasName("Pepe")
      .doAssert();
}

Ahora, para verificar que no estamos en un falso positivo, hacemos una prueba rápida cambiando un par de valores y éste es el resultado que nos muestra:

Wrong value for field 'name'. Expected is 'El Pepe' but actual was 'Pepe'

Vemos cómo nos dice la columna que ha fallado, y el dato que esperaba en comparación con el que recibió de base de datos.

Conclusiones

La solución que hemos planteado aquí requiere de un poco más de tiempo, pero para hacer test “Golden Master, de caracterización o (como lo llamamos en la casa) test arnés”, es bastante útil para ir con seguridad de que los datos se siguen manipulando como se espera.

Esta técnica, como otras útiles, podemos encontrarlas en el libro “Working Effectively with Legacy Code” de Michael C. Feathers, que nos cuenta cómo hacer frente a código legacy, muy acoplado y muchos acoplados. A nosotros nos ha ayudado y esperamos que a ustedes también.

Publicado el 10/05/2023 por

¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.

Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?

Impulsamos el crecimiento profesional de tu equipo de developers