以编程方式启用和禁用 Spring 中的某些 @RabbitListener?
Programmatically enable and disable certain @RabbitListener's in Spring?
我有一个发布事件 E1 的 class A。在用 @RabbitListener
注释的同一应用程序中,E1 由 class B 使用。 B 做一些事情然后发布事件 E2 被 C 等消费(形成一个流程链)。
我想做的是两件事:
- 我想在集成测试中测试 A,但在这样做时我想禁用
RabbitListener's
以便不执行作为 E1 发布结果的整个过程。我只想断言 A 做了它应该做的并发布了 E1。我设法通过设置 spring.rabbitmq.listener.auto-startup=false
. 来解决这个问题
- 我还想通过将 E1 发布到 RabbitMQ 来在集成测试中测试 B,这样我就可以确信我已经正确配置了 B 的
RabbitListerner
。但是我再次不希望 C 被称为 E2 被发布的副作用。
我知道我可能可以使用模拟来做到这一点,但最好我想测试真实的交易并使用实际的组件(包括将消息发送到实际的 RabbitMQ 实例,在我的例子中是 运行在 Docker).
我可以在 Spring 引导中以一种很好的方式实现这一点吗?还是建议使用 @RabbitListenerTest
并确实使用模拟?
@RabbitListener
有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 "";
还有 RabbitListenerEndpointRegistry#getListenerContainer(String)
returns MessageListenerContainer
并且您已经可以控制 start()/stop()
个人 @RabbitListener
处理程序。
follow-up 的想法是拥有某种抽象 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
s 的 ID。
PS:清理当然也可以:
public abstract class BaseAmqpIntegrationTest {
@AfterEach
protected void cleanUpAfterEach() {
rabbitListenerEndpointRegistry.getListenerContainers()
.forEach(Lifecycle::stop);
}
}
或更多 fine-grained:
public abstract class BaseAmqpIntegrationTest {
@AfterEach
protected void cleanUpAfterEach() {
getRequiredListenersToStart().forEach(listener -> rabbitListenerEndpointRegistry.getListenerContainer(listener)
.stop());
}
}
我有一个发布事件 E1 的 class A。在用 @RabbitListener
注释的同一应用程序中,E1 由 class B 使用。 B 做一些事情然后发布事件 E2 被 C 等消费(形成一个流程链)。
我想做的是两件事:
- 我想在集成测试中测试 A,但在这样做时我想禁用
RabbitListener's
以便不执行作为 E1 发布结果的整个过程。我只想断言 A 做了它应该做的并发布了 E1。我设法通过设置spring.rabbitmq.listener.auto-startup=false
. 来解决这个问题
- 我还想通过将 E1 发布到 RabbitMQ 来在集成测试中测试 B,这样我就可以确信我已经正确配置了 B 的
RabbitListerner
。但是我再次不希望 C 被称为 E2 被发布的副作用。
我知道我可能可以使用模拟来做到这一点,但最好我想测试真实的交易并使用实际的组件(包括将消息发送到实际的 RabbitMQ 实例,在我的例子中是 运行在 Docker).
我可以在 Spring 引导中以一种很好的方式实现这一点吗?还是建议使用 @RabbitListenerTest
并确实使用模拟?
@RabbitListener
有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 "";
还有 RabbitListenerEndpointRegistry#getListenerContainer(String)
returns MessageListenerContainer
并且您已经可以控制 start()/stop()
个人 @RabbitListener
处理程序。
follow-up 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
s 的 ID。
PS:清理当然也可以:
public abstract class BaseAmqpIntegrationTest {
@AfterEach
protected void cleanUpAfterEach() {
rabbitListenerEndpointRegistry.getListenerContainers()
.forEach(Lifecycle::stop);
}
}
或更多 fine-grained:
public abstract class BaseAmqpIntegrationTest {
@AfterEach
protected void cleanUpAfterEach() {
getRequiredListenersToStart().forEach(listener -> rabbitListenerEndpointRegistry.getListenerContainer(listener)
.stop());
}
}