如何在模块/集成测试中禁用 Spring SQS 处理程序
Posted
技术标签:
【中文标题】如何在模块/集成测试中禁用 Spring SQS 处理程序【英文标题】:How to disable Spring SQS handler in module/integration test 【发布时间】:2017-10-17 20:32:05 【问题描述】:我有一个 Spring Boot 应用程序,它只是通过具有 @SqsListener 注释方法的组件“MessageHandler”侦听 SQS 队列,并在消息到达时开始一些工作。
还有一个 boot-starter-web 依赖项,因为我们想在生产环境中通过 http 获取健康状态和指标。
现在我想编写一个模块测试,它已经有一个应用程序上下文和自动装配 bean。我还发现了如何禁用测试不需要的 Web 服务器:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = NONE)
但是,MessageHandler bean 也被实例化并尝试连接到 AWS,我想阻止这种情况。
一个可行的解决方案是在 src/test/java 中使用@Primary 注释进行测试实现,其handleMessage 方法没有@SqsListener 注释:
@Component
@Primary
public class TestMessageHandler implements MessageHandler
@Override
public void handleMessage(final NewMessage newMessage) throws Exception
return null;
但是现在我还想测试(真正的)MessageHandler bean,这意味着,我希望 Spring 实例化它并自动装配它的依赖项,但我仍然不希望 @SqsListener 注释变为活动状态,所以我可以在我的测试中这样调用它:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = NONE)
public class IntegrationTest
@Autowired
private RealMessageHandler messageHandler;
@Test
public void testHandleMessage() throws Exception
messageHandler.handleMessage(new NewMessage(...));
所以我需要关闭 spring-cloud-aws-starter 模块的魔法,该模块为 RealMessageHandler 中的 handleMessage 方法设置 SQS 侦听器。
知道我会怎么做吗?
【问题讨论】:
【参考方案1】:我遇到了类似的问题,并通过模拟 SimpleMessageListenerContainer bean 解决了它。我计划为多个集成测试执行此操作,以便让这些测试更具可读性,我创建了一个 @TestConfiguration 类,然后将其导入到测试中。
这是我的配置类:
/**
* Configuration class for integration test that do not need message listening capabilities.
*/
@TestConfiguration
public class MockMessageListenerConfiguration
@MockBean
private SimpleMessageListenerContainer messageListenerContainer;
我是这样使用它的:
@SpringBootTest
@Import(MockMessageListenerConfiguration.class)
class BookingRepositoryIT ...
在此之后,与 AWS SQS 相关的连接拒绝警告消失了。
【讨论】:
【参考方案2】:对于那些想要在不模拟实际队列发送/接收过程的情况下测试应用程序的人,您可以执行以下操作。
在测试中自动装配消息模板,然后像这样禁用侦听器:
@Autowired
private SimpleMessageListenerContainer simpleMessageListenerContainer;
@Autowired
private QueueMessagingTemplate queueMessagingTemplate;
@Test
public void test()
String logicalQueueName = "my-queue";
simpleMessageListenerContainer.stop(logicalQueueName);
// code that will trigger message to be inserted into the queue
Message<?> msg = ((QueueMessagingTemplate) queueMessagingTemplate)
.receive(logicalQueueName);
// process msg
请记住,监听器不会在之后自动启动,因此您可以考虑在测试类中使用 DirtiesContext
注释。
【讨论】:
以上是关于如何在模块/集成测试中禁用 Spring SQS 处理程序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot 2.2.0 的集成测试中禁用安全性?
无法使用测试容器的 localstack 模块连接到 Aws SQS