A partir de Spring Framework 5.3.3, el marco TestContext brinda soporte para registrar eventos de aplicaciones publicados en ApplicationContext para que las pruebas se puedan afirmar contra esos eventos. Todos los eventos publicados durante la ejecución de una única prueba están disponibles a través de la API ApplicationEvents, que permite que los eventos se procesen como java.util.Stream.

Para utilizar ApplicationEvents en sus pruebas, haga lo siguiente.

  • Asegúrese de que su clase de prueba esté anotada o metaanotada con @RecordApplicationEvents.

  • Asegúrese de que ApplicationEventsTestExecutionListener esté registrado. Tenga en cuenta que ApplicationEventsTestExecutionListener está registrado de forma predeterminada y solo necesita registrarlo manualmente si tiene una configuración especial a través de la anotación @TestExecutionListener que no incluye oyentes de forma predeterminada.

  • Anote un campo de tipo ApplicationEvents con la anotación @Autowired y utilice esta instancia de ApplicationEvents en sus métodos de prueba y métodos de ciclo de vida (p. ej. métodos, marcados con las anotaciones @BeforeEach y @AfterEach en JUnit Jupiter).

    • Al utilizar SpringExtension para JUnit Jupiter, puede declarar un parámetro de método de tipo ApplicationEvents en un método de prueba o de ciclo de vida como alternativa a un campo anotado @Autowired en la clase de prueba.

La siguiente clase de prueba usa SpringExtension para JUnit Jupiter y AssertJ para tipos de aserción de eventos de aplicación publicados cuando se llama a un método en un bean administrado Spring:

Java
@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
clase PruebasServicioPedido {
    @autocableado
    Servicio de pedidoServicio de pedido;
    @autocableado
    Eventos de eventos de aplicación; 
    @Prueba
    anular enviarOrder() {
        // Llama a un método en OrderService que publica un evento
        orderService.submitOrder(nuevo pedido(/* ... */));
        // Comprobar que el evento OrderSubmitted ha sido publicado
        long numEvents = events.stream(OrderSubmitted.class).count(); 
        afirmarQue(numEvents).isEqualTo(1);
    }
}
  1. Anote la clase de prueba con @RecordApplicationEvents.
  2. Inyecta una instancia de ApplicationEvents para la prueba actual.
  3. Utilice la API ApplicationEvents para contar cuántos eventos OrderSubmitted se han publicado.
Kotlin
@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
clase PruebasServicioPedido {
    @autocableado
    lateinit var orderService: OrderService
    @autocableado
    eventos lateinit var: ApplicationEvents
    @Prueba
    divertido enviarOrden() {
        // Llama a un método en OrderService que publica el evento
        orderService.submitOrder(Orden(/* ... */))
        // Comprobar que el evento OrderSubmitted ha sido publicado
        val numEvents = eventos.stream(OrderSubmitted::class).count() 
        afirmar que(numEvents).isEqualTo(1)
    }
}
  1. Anote la clase de prueba con @RecordApplicationEvents.
  2. Inyecta una instancia de ApplicationEvents para la prueba actual.
  3. Utilice la API ApplicationEvents para contar cuántos eventos OrderSubmitted se han publicado.

Ver javadoc por ApplicationEvents para obtener más información sobre la API ApplicationEvents.

Eventos de ejecución de prueba

El detector EventPublishingTestExecutionListener, introducido en Spring Framework 5.2, ofrece un enfoque alternativo para implementar un TestExecutionListener personalizado. Los componentes de la prueba ApplicationContext pueden escuchar los siguientes eventos publicados por EventPublishingTestExecutionListener, cada uno de los cuales corresponde a un método en la API TestExecutionListener.

  • BeforeTestClassEvent

  • PrepareTestInstanceEvent

  • BeforeTestMethodEvent

  • BeforeTestExecutionEvent

  • AfterTestExecutionEvent

  • AfterTestMethodEvent

  • AfterTestClassEvent

Estos eventos se pueden consumir por diversos motivos, como restablecer beans simulados o realizar un seguimiento de la ejecución de pruebas. Una ventaja de consumir eventos de ejecución de pruebas en lugar de implementar un TestExecutionListener especial es que los eventos de ejecución de pruebas pueden ser consumidos por cualquier Spring Bean registrado en el ApplicationContext de prueba, y dichos beans pueden directamente inyección de dependencia de beneficios y otras funciones ApplicationContext. Por el contrario, TestExecutionListener no es un bean en ApplicationContext.

El oyente EventPublishingTestExecutionListener está registrado de forma predeterminada; sin embargo, solo publica eventos si el ApplicationContext ya está cargado. Esto evita que ApplicationContext se cargue innecesariamente o demasiado pronto.

Por lo tanto, el evento BeforeTestClassEvent solo se publicará después de que otro TestExecutionListener haya cargado el ApplicationContext. Por ejemplo, con un conjunto de implementaciones TestExecutionListener registradas de forma predeterminada, el evento BeforeTestClassEvent no se publicará para la primera clase de prueba que utilice un de prueba particular ApplicationContext, pero el evento The BeforeTestClassEvent se se publicará para cualquier clase de prueba posterior en el mismo conjunto de pruebas que utilice el mismo ApplicationContext de prueba, ya que el contexto ya se cargará cuando se ejecuten las siguientes clases de prueba (a menos que el contexto se haya eliminado de ContextCache mediante la anotación @DirtiesContext o la política de desalojo cuando el tamaño máximo se alcanza).

Si desea que siempre se publique un evento BeforeTestClassEvent para cada clase de prueba, debe registrar un TestExecutionListener que cargue el ApplicationContext. en la devolución de llamada >beforeTestClass, y este TestExecutionListener debe estar registrado antes EventPublishingTestExecutionListener.

De manera similar, si la anotación @DirtiesContext se usa para eliminar ApplicationContext del caché de contexto después del último método de prueba en una clase de prueba determinada, el AfterTestClassEvent evento no se publicará para esta clase de prueba.

Para escuchar los eventos de ejecución de pruebas, un Spring Bean puede optar por implementar la interfaz org.springframework.context.ApplicationListener. Además, los métodos de escucha pueden anotarse con @EventListener y configurarse para escuchar uno de los tipos de eventos específicos enumerados anteriormente (consulte Oyentes (receptores) de eventos basados en anotaciones).
Debido a la popularidad de este enfoque, Spring proporciona las siguientes anotaciones especiales @EventListener para facilitar el registro de detectores de eventos de ejecución de pruebas. Estas anotaciones están en el paquete org.springframework.test.context.event.annotation.

  • @BeforeTestClass

  • @PrepareTestInstance

  • @BeforeTestMethod

  • @BeforeTestExecution

  • @AfterTestExecution

  • @AfterTestMethod

  • @AfterTestClass

Manejo de excepciones

De forma predeterminada, si un detector de eventos de ejecución de prueba genera una excepción al consumir un evento, esa excepción se lanza al marco de prueba subyacente que se está utilizando (como JUnit o TestNG). Por ejemplo, si consumir un evento BeforeTestMethodEvent genera una excepción, entonces el método de prueba correspondiente fallará como resultado de esa excepción. Por el contrario, si un detector de eventos de ejecución de prueba asincrónica genera una excepción, no se propaga al marco de prueba subyacente. Para obtener más información sobre el manejo de excepciones asíncrono, consulte el javadoc en @EventListener a nivel de clase.

Oyentes asincrónicos

Si desea que un detector de eventos de ejecución de prueba específico procese eventos de forma asincrónica, puede utilizar soporte de anotaciones regulares @Async de Spring.
Para obtener más detalles, consulte el javadoc en @EventListener a nivel de clase.