Skip to main content

Matchers personalizados en AssertJ

⏱ Dedicación recomendada: 0 minutos
Esto considera el contenido visible y relevante, e ignora texto colapsado o marcado como opcional.


r8vnhill/java-dibs

Existen dos formas de crear matchers personalizados en AssertJ. La primera es crear un objeto de tipo Condition y la segunda es extender la clase AbstractAssert.

Creación de un matcher con Condition

Para crear un matcher que verifique si un número es par, utilizamos la clase Condition de AssertJ:

public static Condition<Integer> even =
new Condition<>(value -> value % 2 == 0, "even");
¿Qué acabamos de hacer?

Creamos un objeto Condition que verifica si un número es par. El constructor de Condition recibe una expresión lambda que evalúa la condición y un mensaje de error en caso de fallo.

Uso del matcher en pruebas

assertThat(2).is(even);
assertThrows(AssertionError.class, () -> assertThat(2).isNot(even));
assertThat(3).isNot(even);
assertThrows(AssertionError.class, () -> assertThat(3).is(even));
¿Qué acabamos de hacer?
  • En el código de prueba, utilizamos el matcher even para verificar si un número es par.
  • La aserción assertThat(2).is(even) verifica si el número 2 es par, mientras que assertThat(3).isNot(even) verifica si el número 3 no es par.

Creación de un Matcher con AbstractAssert

Para crear un matcher personalizado en AssertJ, podemos extender la clase AbstractAssert. Este enfoque permite crear verificaciones específicas con una sintaxis fluida y fácilmente integrable en las pruebas. En este ejemplo, crearemos un matcher para verificar si un número es par.

public final class EvenNumberAssert
extends AbstractAssert<EvenNumberAssert, Integer> {

public EvenNumberAssert(Integer actual) {
super(actual, EvenNumberAssert.class);
}

public static @NotNull EvenNumberAssert assertThat(Integer actual) {
return new EvenNumberAssert(actual);
}

public EvenNumberAssert isEven() {
isNotNull();
if (actual % 2 != 0) {
failWithMessage(
"Expected <%s> to be even, but it was not.",
actual
);
}
return this;
}
}
¿Qué acabamos de hacer?
  • La clase EvenNumberAssert hereda de AbstractAssert, lo que permite definir métodos de aserción personalizados.
  • El método assertThat() actúa como un punto de entrada estático, creando una instancia de EvenNumberAssert que facilita su uso en pruebas.
  • El método isEven() comprueba si el número actual (actual) es par; si no lo es, lanza un mensaje de error personalizado para hacer la falla de la prueba más comprensible.

Uso del Matcher en Pruebas

Para probar el matcher personalizado isEven, podemos crear dos casos de prueba: uno donde la verificación de paridad pase y otro donde falle.

assertThat(2).isEven();
assertThrows(AssertionError.class, () -> assertThat(3).isEven());

Resumen comparativo

CaracterísticaAssertJKotest
Definición de matchers personalizadosEn AssertJ, se pueden crear matchers personalizados extendiendo AbstractAssert o utilizando Condition. Esto permite realizar validaciones complejas y personalizadas mediante clases que heredan funcionalidad base.En Kotest, los matchers personalizados se definen implementando la interfaz Matcher<T>, lo que simplifica la creación de validaciones específicas sin necesidad de crear clases enteras.
Sintaxis fluidaAssertJ ofrece una sintaxis fluida y encadenable, permitiendo múltiples validaciones en una sola línea (isEven().isGreaterThan()).Kotest también ofrece una sintaxis fluida con operadores como should y shouldNot, lo que facilita la creación de pruebas expresivas y legibles.
CompatibilidadEstá diseñado principalmente para Java, lo que lo hace ideal para proyectos que utilizan el ecosistema Java.Kotest está optimizado para Kotlin, aprovechando las características de este lenguaje, como coroutines y expresiones lambda.
Flexibilidad para crear matchersEn AssertJ, los matchers personalizados requieren más configuración, especialmente si se utiliza AbstractAssert. Sin embargo, este enfoque ofrece más control en casos complejos.Crear un matcher en Kotest es más sencillo y directo. Basta con implementar Matcher<T> y definir las condiciones.
Soporte para asincroníaAssertJ no tiene soporte nativo para asincronía, lo que puede ser una limitación en proyectos que dependen de operaciones concurrentes o asíncronas.Kotest soporta asincronía nativamente, integrando coroutines y facilitando las pruebas de código que utiliza operaciones asíncronas.
Uso en JVM y KotlinAunque AssertJ se puede utilizar en proyectos Kotlin, no está diseñado específicamente para este lenguaje, lo que puede limitar la integración perfecta con características avanzadas de Kotlin.Kotest está diseñado específicamente para Kotlin y la JVM, lo que garantiza una integración más fluida y un mejor uso de las características del lenguaje.

Beneficios y limitaciones

Beneficios

  • Sintaxis fluida y encadenable: AssertJ ofrece una sintaxis fluida que permite encadenar múltiples validaciones en una sola línea, lo que facilita la lectura y mejora la expresividad de las pruebas.
  • Flexibilidad en la creación de matchers: Con AssertJ, los matchers personalizados se pueden definir usando Condition para situaciones simples o extendiendo AbstractAssert para validaciones más complejas. Esto ofrece flexibilidad dependiendo del nivel de personalización necesario.
  • Amplia compatibilidad con Java: AssertJ está bien integrado en el ecosistema de Java, haciéndolo una opción ideal para proyectos Java que requieren una biblioteca rica en funcionalidad para pruebas.
  • Personalización avanzada: Al extender AbstractAssert, se puede obtener un control total sobre cómo se manejan las validaciones y los mensajes de error, lo que permite personalizar cada detalle del matcher.

Limitaciones

  • Complejidad en la creación de matchers: Comparado con Kotest, crear matchers personalizados en AssertJ puede ser más complejo y requiere más configuración, especialmente si se utiliza AbstractAssert.
  • Falta de soporte para asincronía: AssertJ no tiene soporte nativo para operaciones asíncronas, lo que puede ser un inconveniente en proyectos que dependen de procesos concurrentes o asíncronos.
  • Menor integración con Kotlin: Aunque AssertJ puede ser utilizado en proyectos Kotlin, no está optimizado para este lenguaje, lo que significa que puede no aprovechar completamente las características avanzadas de Kotlin, como coroutines o lambdas.
  • Mayor carga de configuración: Mientras que Kotest permite crear matchers personalizados de manera sencilla implementando una interfaz, AssertJ requiere la creación de clases completas y métodos adicionales, lo que puede aumentar la carga de configuración para casos complejos.

¿Qué aprendimos?

En esta lección, hemos comparado la creación de matchers personalizados entre AssertJ y Kotest, observando las diferencias clave en cómo se definen y utilizan estos matchers en cada marco de pruebas.

Puntos clave

  1. Matchers Personalizados en AssertJ:
    • AssertJ permite crear matchers personalizados de dos formas: mediante Condition o extendiendo la clase AbstractAssert. Esto ofrece flexibilidad para validar condiciones complejas.
    • La creación de matchers mediante AbstractAssert proporciona un alto grado de control sobre las validaciones y los mensajes de error, pero también implica mayor complejidad y configuración.
  2. Matchers Personalizados en Kotest:
    • Kotest facilita la creación de matchers personalizados mediante la implementación de la interfaz Matcher<T>. Este enfoque es más sencillo y directo, ideal para validaciones que no requieren una estructura compleja.
    • Kotest está diseñado para Kotlin, lo que permite aprovechar sus características avanzadas, como las coroutines, para soportar asincronía nativa en las pruebas.
  3. Diferencias Notables:
    • Sintaxis: Ambos frameworks ofrecen una sintaxis fluida y encadenable, aunque AssertJ destaca por su enfoque más Java y Kotest por su integración nativa con Kotlin.
    • Asincronía: Kotest tiene una ventaja en proyectos que requieren pruebas de código asíncrono, ya que soporta nativamente coroutines. AssertJ, por otro lado, no tiene soporte nativo para asincronía.
    • Carga de configuración: AssertJ puede requerir más configuración al crear matchers complejos, mientras que Kotest simplifica el proceso mediante la interfaz Matcher<T>.

Ambos frameworks son útiles para la creación de matchers personalizados, pero la elección depende del lenguaje y las necesidades del proyecto. AssertJ es ideal para proyectos en Java que requieren un alto control y flexibilidad, mientras que Kotest es más adecuado para proyectos Kotlin que buscan simplicidad, soporte para asincronía y una integración más fluida con el lenguaje.

Bibliografías Recomendadas