Manera limpia de iniciar un sondeador de integración de Spring en la prueba de integración de JUnit

Resuelto usr-local-ΕΨΗΕΛΩΝ asked hace 9 meses • 1 respuestas

Tengo un flujo de Spring Integration que utiliza un MessageSourcepara completar periódicamente mensajes de una consulta de base de datos (no, no tenía intención de usar Spring Integration JPA/JDBC)

@Bean
public IntegrationFlow messageTimeout(
        ReadTimeoutsMessageSource readTimeoutsMessageSource,
        UpdatePaymentWithStatusTimeoutHandler updatePaymentWithStatusTimeoutHandler
) {
    return IntegrationFlow
            /*
             *   Read from OraIpTask procedure
             */
            .from(readTimeoutsMessageSource, s -> s
                    .id("messageTimeout.readTimeouts")
                    .poller(Pollers.fixedDelay(Duration.ofMinutes(1), Duration.ofSeconds(10)))
            )
            .split(s -> s.requiresReply(false))
            .bridge(b -> b
                    .id("messageTimeout.bridge")
                    .taskScheduler(messageTimeoutScheduler())
            )
            /*
             * Log a warning
             */
            .log(LoggingHandler.Level.WARN, dto -> "Found timeout: " + dto)
            /*
                Update Payment with status timeout
             */
            .handle(updatePaymentWithStatusTimeoutHandler, h -> h.id("updatePaymentWithStatusTimeoutFlow.updatePaymentWithStatusTimeout"))
            /*
                Discard the message
             */
            .nullChannel();
}

Vayamos al grano: el sondeador tiene un retraso inicial de 10 segundos, y en las pruebas de Junit para este flujo no quiero esperar un tiempo precioso.

La prueba simula un procedimiento almacenado para devolver datos y espero que se construya un mensaje en consecuencia. Solo quiero probar que cada fila del mensaje sea consumida por el finalhandler sin tener que esperar.

¿Hay alguna manera de decirle a Spring que inicie el sondeador instantáneamente durante la prueba y/o que lo ejecute una vez?

Como alternativa, podría construir el mensaje por mi cuenta y utilizarMockIntegrationContext.substituteMessageSourceFor con el mensaje simulado. No lo he probado todavía. Solicito obtener más información sobre Spring Integration y la forma más limpia de realizar pruebas automatizadas.

¡Gracias por el consejo!

Aceptado

La forma de hacerlo ahora es así:

  1. Marcas tu clase de prueba con @SpringIntegrationTest(noAutoStartup ="messageTimeout.readTimeouts"). Incluso si no utiliza simulacros, aún le gustaría tener control sobre ese SourcePollingChannelAdapterciclo de vida: prepare el procedimiento y el activador respectivo para el sondeador. Por lo tanto, es mejor detener ese punto final antes de que esté listo para la prueba.

  2. Lo que haces en la clase de prueba:

    @Autowired
    @Qualifier("messageTimeout.readTimeouts")
    SourcePollingChannelAdapter readTimeoutsEndpoint;
    
  3. En el método de prueba (o cómo prepara los datos de su prueba), usted hace:

    this.readTimeoutsEndpoint.setTrigger(new OnlyOnceTrigger());
    this.readTimeoutsEndpoint.start();
    

Y el consumo de sus datos se producirá de inmediato.

Creo que podemos introducir algo comoMockIntegrationContext.substituteTriggerFor(String pollingAdapterId, Trigger trigger, boolean autoStartup) para hacerlo obvio.

¡Siéntete libre de plantear un problema de GH por eso! Por ahora creo que la solución que te diste es la que estás buscando.

Artem Bilan avatar Feb 15 '2024 16:02 Artem Bilan