问题测试spring cloud SQS Listener

时间:2018-05-31 22:06:33

标签: spring-cloud spring-cloud-aws

环境

  • Spring Boot:1.5.13.RELEASE
  • 云:Edgware.SR3
  • Cloud AWS:1.2.2.RELEASE
  • Java 8
  • OSX 10.13.4

问题

我正在尝试为SQS编写集成测试。

我有一个本地运行localstack docker容器,其中SQS在TCP/4576上运行

在我的测试代码中,我定义了一个端点设置为本地4576的SQS客户端,可以成功连接并创建队列,发送消息和删除队列。我也可以使用SQS客户端接收消息并获取我发送的消息。

我的问题是,如果我删除手动接收消息的代码,以便允许其他组件获取消息似乎没有发生任何事情。我有一个弹簧组件注释如下:

监听

@Component
public class MyListener {
@SqsListener(value = "my_queue", deletionPolicy = ON_SUCCESS)
    public void receive(final MyMsg msg) {
        System.out.println("GOT THE MESSAGE: "+ msg.toString());
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
public class MyTest {

    @Autowired
    private AmazonSQSAsync amazonSQS;

    @Autowired
    private SimpleMessageListenerContainer container;

    private String queueUrl;

    @Before
    public void setUp() {
        queueUrl = amazonSQS.createQueue("my_queue").getQueueUrl();
    }

    @After
    public void tearDown() {
        amazonSQS.deleteQueue(queueUrl);
    }

    @Test
    public void name() throws InterruptedException {
        amazonSQS.sendMessage(new SendMessageRequest(queueUrl, "hello"));
        System.out.println("isRunning:" + container.isRunning());
        System.out.println("isActive:" + container.isActive());
        System.out.println("isRunningOnQueue:" + container.isRunning("my_queue"));
        Thread.sleep(30_000);
        System.out.println("GOT MESSAGE: " + amazonSQS.receiveMessage(queueUrl).getMessages().size());
    }

    @TestConfiguration
    @EnableSqs
    public static class SQSConfiguration {

        @Primary
        @Bean(destroyMethod = "shutdown")
        public AmazonSQSAsync amazonSQS() {
            final AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration("http://127.0.0.1:4576", "eu-west-1");
            return new AmazonSQSBufferedAsyncClient(AmazonSQSAsyncClientBuilder
                    .standard()
                    .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("key", "secret")))
                    .withEndpointConfiguration(endpoint)
                    .build());
        }
    }
}

在测试日志中,我看到:

  

o.s.c.a.m.listener.QueueMessageHandler:在MyListener类上找到1个消息处理程序方法:{public void MyListener.receive(MyMsg)=org.springframework.cloud.aws.messaging.listener.QueueMessageHandler$MappingInformation@1cd4082a}   2018-05-31 22:50:39.582 INFO 16329 ---

     

o.s.c.a.m.listener.QueueMessageHandler:Mapped" org.springframework.cloud.aws.messaging.listener.QueueMessageHandler$MappingInformation@1cd4082a" on public void MyListener.receive(MyMsg)

其次是:

  

isRunning:真

     

isActive:真

     

isRunningOnQueue:假

     

GOT MESSAGE:1

这表明在发送消息之间的30秒暂停中,容器没有将其取出,当我手动轮询消息时,它就在队列中,我可以使用它。

我的问题是,为什么不调用侦听器?为什么isRunningOnQueue:false行表明该队列没有自动启动?

请注意,我还尝试将自己的SimpleMessageListenerContainer bean设置为true,显式设置为true(无论如何都是默认值),并观察到行为没有变化。我认为org.springframework.cloud.aws.messaging.config.annotation.SqsConfiguration#simpleMessageListenerContainer设置的@EnableSqs应该配置一个自动启动SimpleMessageListenerContainer,应该为我查询消息。

我也设置了

logging.level.org.apache.http=DEBUG
logging.level.org.springframework.cloud=DEBUG

在我的测试属性中,可以看到HTTP调用创建队列,发送消息和删除等但没有HTTP调用接收(除了我在测试结束时的手册)。

1 个答案:

答案 0 :(得分:1)

经过一些修修补补后,我想出了这个。

即使简单的消息容器工厂设置为不自动启动,它似乎也会进行初始化,这涉及确定队列是否存在。

在这种情况下,队列是在我的测试中在setup方法中创建的 - 但遗憾的是,这是在设置spring上下文后意味着发生异常。

我通过简单地将队列创建移动到SQS客户端的上下文创建(在创建消息容器之前发生)来修复此问题。即:

@Bean(destroyMethod = "shutdown")
        public AmazonSQSAsync amazonSQS() {
            final AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration("http://localhost:4576", "eu-west-1");
            final AmazonSQSBufferedAsyncClient client = new AmazonSQSBufferedAsyncClient(AmazonSQSAsyncClientBuilder
                    .standard()
                    .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("dummyKey", "dummySecret")))
                    .withEndpointConfiguration(endpoint)
                    .build());
            client.createQueue("test-queue");
            return client;
        }