当前位置: 首页 > 知识库问答 >
问题:

在读取ActiveMQ队列时,如何防止Spring JmsTemplate单元测试阻塞?

侯池暝
2023-03-14

当试图从ActiveMQ队列读取Person对象时,我如何防止Spring JmsTemboard单元测试sendAndReceivePerson()阻塞?

测试创建一个Person对象,将其发送到队列person.queue(这也应该创建包含队列的嵌入式代理),然后尝试从同一队列中读取该对象。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MessagingConfiguration.class})
public class PersonMessengerTest {
    @Autowired
    private PersonMessenger personMessenger;

    @Test
    public void sendAndReceivePerson() {
        final Person person = new Person();
        final UUID id = UUID.randomUUID();
        person.setId(id);
        person.setFirstName("Derek");
        person.setLastName("Mahar");
        personMessenger.sendPersion(person);
        final Person receivedPersion = personMessenger.receivePersion();
        assertEquals(id, receivedPersion.getId());
    }
}

public class PersonMessenger {

    private final JmsOperations jmsOperations;

    public PersonMessenger(JmsOperations jmsOperations) {
        this.jmsOperations = jmsOperations;
    }

    public void sendPersion(final Person person) {
        this.jmsOperations.convertAndSend(person);
    }

    public Person receivePersion() {
        return (Person) this.jmsOperations.receiveAndConvert();
    }
}

@Configuration
@Import({CommonConfiguration.class})
public class MessagingConfiguration {

    public static final String PERSON_QUEUE = "person.queue";

    @Autowired
    private ApplicationEnvironment applicationEnvironment;

    @Bean
    public ConnectionFactory jmsConnectionFactory() {
        final ActiveMQConnectionFactory activeMqConnectionFactory = new ActiveMQConnectionFactory(
                this.applicationEnvironment.getJmsBrokerUrl());
        activeMqConnectionFactory.setTrustAllPackages(true);
        return activeMqConnectionFactory;
    }

    @Bean
    public JmsOperations jmsTemplate(ConnectionFactory connectionFactory) {
        final JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
        jmsTemplate.setDefaultDestinationName(PERSON_QUEUE);
        return jmsTemplate;
    }

    @Bean
    public PersonMessenger personMessenger(JmsOperations jmsOperations) {
        return new PersonMessenger(jmsOperations);
    }

    @Bean(name = PERSON_QUEUE)
    public Queue personQueue() {
        return new ActiveMQQueue(PERSON_QUEUE);
    }
}

@Configuration
@PropertySource("classpath:application.properties")
public class CommonConfiguration {

    @Autowired
    private Environment applicationEnvironment;

    @Bean
    public ApplicationEnvironment applicationEnvironment() {
        return new ApplicationEnvironment(this.applicationEnvironment);
    }
}

application.properties:

jms.brokerUrl=vm://test?async=false&broker.persistent=false&broker.useJmx=false

请注意,当试图从队列中读取Person对象时,测试会阻塞:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.opessoftware.example.spring.messenger.PersonMessengerTest
2017-02-15 15:30:33,736|WARN|main|o.a.activemq.broker.BrokerService|49670|
    org.apache.activemq.broker.BrokerService.checkMemorySystemUsageLimits(BrokerService.java:2142)
    Memory Usage for the Broker (1024mb) is more than the maximum available for the JVM: 955 mb - resetting to 70% of maximum available: 668 mb
2017-02-15 15:30:33,993|WARN|main|o.a.activemq.broker.BrokerService|49927|
    org.apache.activemq.broker.BrokerService.checkMemorySystemUsageLimits(BrokerService.java:2142)
    Memory Usage for the Broker (1024mb) is more than the maximum available for the JVM: 955 mb - resetting to 70% of maximum available: 668 mb

receiveAndConvert()调用是在创建第二个嵌入式代理,还是在从其他队列读取?

共有2个答案

百里成仁
2023-03-14

正如Gary Russell所建议的,为了防止每个JMS操作关闭连接并丢弃嵌入的代理以及队列中的Person消息,方法jmsConnectionFactory()在配置类MessagingConfiguration中,现在将ActiveMQConnectionFactory(实现ConnectionFactory)包装在CachingConnectionFactory中:

@Configuration
@Import({CommonConfiguration.class})
@EnableJms
public class MessagingConfiguration {

    public static final String PERSON_QUEUE = "person.queue";

    @Autowired
    private ApplicationEnvironment applicationEnvironment;

    @Bean
    public ConnectionFactory jmsConnectionFactory() {
        final ActiveMQConnectionFactory activeMqConnectionFactory = new ActiveMQConnectionFactory(
                this.applicationEnvironment.getJmsBrokerUrl());
        activeMqConnectionFactory.setTrustAllPackages(true);
        return new CachingConnectionFactory(activeMqConnectionFactory);
    }

    @Bean
    public JmsOperations jmsTemplate(ConnectionFactory connectionFactory) {
        final JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
        jmsTemplate.setDefaultDestinationName(PERSON_QUEUE);
        return jmsTemplate;
    }

    @Bean
    public PersonMessenger personMessenger(JmsOperations jmsOperations) {
        return new PersonMessenger(jmsOperations);
    }

    @Bean(name = PERSON_QUEUE)
    public Queue personQueue() {
        return new ActiveMQQueue(PERSON_QUEUE);
    }
}

请注意,下面的测试只传递和输出一个BrokerService内存警告,这意味着测试只创建一个所有JMS操作都使用的嵌入式代理。

------------------------------------------------------------------------
Building spring-hibernate-jpa 1.0.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-surefire-plugin:2.10:test (default-cli) @ spring-hibernate-jpa ---
Surefire report directory: /home/derek/Projects/spring-hibernate-jpa/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.opessoftware.example.spring.messenger.PersonMessengerTest
2017-02-16 10:14:03,743|WARN|main|o.a.activemq.broker.BrokerService|1579|
    org.apache.activemq.broker.BrokerService.checkMemorySystemUsageLimits(BrokerService.java:2142)
    Memory Usage for the Broker (1024mb) is more than the maximum available for the JVM: 955 mb - resetting to 70% of maximum available: 668 mb
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.929 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 4.190s
Finished at: Thu Feb 16 10:14:04 EST 2017
Final Memory: 8M/60M
------------------------------------------------------------------------
况繁
2023-03-14

使用嵌入式代理进行测试时,这是一个臭名昭著的问题。

操作之间的连接被关闭,如果没有持久性,数据将丢失。

尝试将连接工厂包装在一个CachingConnectionFactory中,以便连接保持打开状态(因此代理保持打开状态)。

无论如何,出于性能原因,您应该将CachingConnectionFactoryJmsTemplate结合使用,但在单元测试中尤其糟糕。

 类似资料:
  • Rspec尝试在运行任何规范文件或整个测试套件的末尾运行测试::单元测试。它仍然可以,因为我没有任何测试单元测试文件,但它尝试将给定给rspec的命令行选项传递给test::unit,结果是 如何阻止rspec运行测试单元测试? 我正在使用的测试gem版本是

  • 问题内容: 我有多个包含要发送的消息的BlockingQueues。消费者数量可能少于队列数量吗?我不想遍历队列并继续轮询它们(忙于等待),并且我不想为每个队列都分配一个线程。相反,当任何队列中都有消息可用时,我想唤醒一个线程。 问题答案: 您可以做的一个技巧是让队列排队。因此,您要做的是只有一个阻塞队列,所有线程都订阅该队列。然后,当您将某些内容排队到其中一个BlockingQueues中时,您

  • 我需要在我的应用程序中进行单元测试JMSXGroupID。有人能告诉我是否有示例文章或参考文献来实现这一点吗?我试图在ActiveMQ门户中查看参考文献,但看起来下面的Hudson链接坏了。我正在使用Spring JMS进行编程。 http://activemq.apache.org/junit-reports.html

  • 我有一个查询语句,它返回,并将其分配给一个列表。然后我在单子上操作。 如何在列表执行时发送该列表。 其动机是在执行时将构造的列表发送到。 注:

  • 我有一个Java项目,它使用了一些Azure函数,如HttpTrigger和QueueTrigger。我使用原型来生成这个项目,因此它可以使用HttpTrigger的一些样板代码和它的单元测试,但对QueueTrigger没有任何帮助。我正试图得到帮助,为这个QueueTrigger编写一个好的单元测试,它实际上是从队列中读取消息(弹出)。队列的代码如下所示: 有没有人能推荐一下这个队列触发azu