Equals
En el contexto de pruebas unitarias en Java, es común la necesidad de comparar instancias de objetos personalizados para verificar que su contenido sea igual al esperado. Por defecto, la comparación entre objetos con assertEquals(obj1, obj2) verifica si ambos hacen referencia al mismo objeto en memoria. Esto implica que, salvo que se sobrescriba correctamente el método equals, dos objetos distintos aunque con atributos idénticos no serán considerados iguales.
¿Qué es equals y por qué sobrescribirlo?
Sección titulada «¿Qué es equals y por qué sobrescribirlo?»El método equals es heredado por todas las clases en Java desde la clase Object y su implementación por defecto evalúa si dos referencias apuntan al mismo objeto (==). Para realizar comparaciones lógicas o estructurales entre objetos (es decir, comparar sus atributos), se debe sobrescribir (override) este método.
Ejemplo sin sobrescribir equals
Sección titulada «Ejemplo sin sobrescribir equals»Persona p1 = new Persona("Nataly", 21);Persona p2 = new Persona("Nataly", 21);
System.out.println(p1.equals(p2)); // falseA pesar de tener los mismos valores, el resultado es false porque equals no está sobrescrito y compara referencias.
¿Qué implica sobrescribir equals?
Sección titulada «¿Qué implica sobrescribir equals?»Para que las pruebas unitarias puedan validar correctamente la igualdad lógica de objetos, se debe proporcionar una implementación personalizada del método equals, que compare uno a uno los atributos relevantes de la clase.
@Overridepublic boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false;
Persona persona = (Persona) obj; return edad == persona.edad && nombre.equals(persona.nombre);}¿Qué es la anotación @Override?
Sección titulada «¿Qué es la anotación @Override?»@Override es una anotación que indica al compilador que un método sobrescribe una versión existente en una superclase. Su uso no es obligatorio, pero altamente recomendable por las siguientes razones:
-
Permite al compilador verificar que realmente se está sobrescribiendo un método existente.
-
Previene errores por errores tipográficos o de firma del método.
Por ejemplo, si se escribeequalen lugar deequals, sin@Overrideel compilador lo acepta como un método nuevo, lo que provoca un fallo lógico en tiempo de ejecución y en las pruebas.
Sin @Override:
Sección titulada «Sin @Override:»public boolean equals(Object obj) { // Puede contener errores y el compilador no lo advertirá.}Con @Override:
Sección titulada «Con @Override:»@Overridepublic boolean equals(Object obj) { // Verificado por el compilador.}Importancia en pruebas unitarias
Sección titulada «Importancia en pruebas unitarias»En pruebas con frameworks como JUnit, el método assertEquals(obj1, obj2) utiliza internamente el método equals del primer objeto (obj1.equals(obj2)). Por tanto:
-
Si
equalsno está sobrescrito, la prueba fallará incluso si los objetos son visualmente iguales. -
Si
equalsestá sobrescrito correctamente, se garantiza una comparación lógica exacta, lo cual es fundamental para verificar estados esperados en objetos complejos.