Tengo una clase A que publica el evento E1. E1 es consumido por la clase B en la misma aplicación que está anotada con @RabbitListener . B hace algunas cosas y luego publica el evento E2 que es consumido por C, etc., etc. (formando una cadena de procesos).
Lo que quiero hacer son dos cosas:
RabbitListener's para que no se ejecute todo el proceso que es el resultado de la publicación de E1. Solo quiero afirmar que A hace lo que se supone que debe hacer y publica E1. Me las arreglé para acomodar esto configurando spring.rabbitmq.listener.auto-startup=false .RabbitListerner de B correctamente. Pero nuevamente, no quiero que se llame a C como un efecto secundario de la publicación de E2.Sé que probablemente pueda hacer esto usando simulacros, pero preferiblemente me gustaría probar el trato real y usar los componentes reales (incluido el envío del mensaje a una instancia real de RabbitMQ que, en mi caso, se ejecuta en Docker).
¿Puedo lograr esto de una manera agradable en Spring Boot? ¿O tal vez se recomienda usar @RabbitListenerTest y, de hecho, usar simulacros?
@RabbitListener tiene la propiedad id :
/** * The unique identifier of the container managing for this endpoint. * <p>If none is specified an auto-generated one is provided. * @return the {@code id} for the container managing for this endpoint. * @see org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry#getListenerContainer(String) */ String id() default ""; Y ese RabbitListenerEndpointRegistry#getListenerContainer(String) devuelve MessageListenerContainer y allí ya puede controlar start()/stop() del controlador @RabbitListener individual.
Una idea de seguimiento de la respuesta aceptada es tener algún tipo de BaseAmqpIntegrationTest abstracto que haga lo siguiente:
public abstract class BaseAmqpIntegrationTest { @Autowired protected RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry; @BeforeEach protected void setUpBeforeEach() { rabbitListenerEndpointRegistry.getListenerContainers() .forEach(Lifecycle::stop); getRequiredListenersToStart().forEach(listener -> rabbitListenerEndpointRegistry.getListenerContainer(listener) .start()); } protected abstract List<String> getRequiredListenersToStart(); } Esto lo hace reutilizable y garantiza que todos los @RabbitListener estén deshabilitados "de forma predeterminada" y requiere que cada prueba habilite explícitamente a los oyentes que prueba. Las subclases de prueba pueden anular simplemente getRequiredListenersToStart() para proporcionar los ID de los @RabbitListener que requieren.
PD: Limpiarlo, por supuesto, también funcionaría:
public abstract class BaseAmqpIntegrationTest { @AfterEach protected void cleanUpAfterEach() { rabbitListenerEndpointRegistry.getListenerContainers() .forEach(Lifecycle::stop); } }O un poco más detallado:
public abstract class BaseAmqpIntegrationTest { @AfterEach protected void cleanUpAfterEach() { getRequiredListenersToStart().forEach(listener -> rabbitListenerEndpointRegistry.getListenerContainer(listener) .stop()); } }