在Spring中以编程方式启用和禁用某些@ RabbitListener?

时间:2017-04-12 09:08:45

标签: java spring rabbitmq integration-testing spring-amqp

我有一个发布事件E1的A类。 E1在由@RabbitListener注释的同一应用程序中由B类使用。 B做了一些事情然后发布了由C等消耗的事件E2(形成一个流程链)。

我想做的是两件事:

  1. 我想在集成测试中测试A但是在这样做时我想禁用RabbitListener's,以便不执行作为E1发布结果的整个过程。我只想断言A做了它应该发布的并发布了E1。我设法通过设置spring.rabbitmq.listener.auto-startup=false
  2. 来实现这一目标
  3. 我还希望通过将E1发布到RabbitMQ来在集成测试中测试B,这样我就可以确信我已正确配置了B RabbitListerner。但我再也不希望C被称为E2的副作用。
  4. 我知道我可以使用模拟做到这一点但最好是我想测试真实的交易并使用实际的组件(包括将消息发送到实际的RabbitMQ实例,在我的情况下是在Docker中运行)。

    我可以在Spring Boot中以一种很好的方式实现这一目标吗?或者是否建议使用@RabbitListenerTest并确实使用模拟?

2 个答案:

答案 0 :(得分:5)

@RabbitListenerid属性:

/**
 * 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 "";

RabbitListenerEndpointRegistry#getListenerContainer(String)返回MessageListenerContainer,您已经可以控制start()/stop()个人@RabbitListener处理程序。{/ p>

答案 1 :(得分:0)

accepted answer的后续想法是拥有某种抽象的BaseAmqpIntegrationTest,它可以完成以下任务:

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();

}

这使得它可以重用,并确保所有“ @RabbitListener”都被“默认”禁用,并且要求每个测试显式启用它测试的侦听器。然后,测试子类可以简单地重写getRequiredListenersToStart()来提供它们所需的@RabbitListener的ID。

PS:清理它当然也可以:

public abstract class BaseAmqpIntegrationTest {

    @AfterEach
    protected void cleanUpAfterEach() {
        rabbitListenerEndpointRegistry.getListenerContainers()
                                      .forEach(Lifecycle::stop);
    }

}

或更细粒度:

public abstract class BaseAmqpIntegrationTest {

    @AfterEach
    protected void cleanUpAfterEach() {
        getRequiredListenersToStart().forEach(listener -> rabbitListenerEndpointRegistry.getListenerContainer(listener)
                                                                                        .stop());
    }

}