Mil*_*nov 14 java activemq-classic jms spring-boot
我有一个非常标准的设置JMS- Spring Boot和ActiveMQ.它工作正常,直到我尝试进行简单的集成测试.经过一些调查后,我发现在第一个JMS消息被消耗后,Spring上下文和嵌入式代理都被关闭,无论消费过程中是什么,都会触发另一个事件.经纪人问题我能够通过useShutdownHook=false在测试设置中添加连接选项来解决,即
spring.activemq.broker-url = vm://broker?async=false&broker.persistent=false&broker.useShutdownHook=false
Run Code Online (Sandbox Code Playgroud)
我正在寻找的基本上是一种强制测试"保持活力"的方法,直到消耗掉所有JMS消息(在这种情况下它们只是两个).我理解整个设置的异步性质,但是在测试期间,生成和使用这些消息的所有结果会很有帮助.
下面是我的设置,虽然它很简单.
@EnableJms
public class ActiveMqConfig {
@Bean
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setMessageConverter(messageConverter);
return jmsTemplate;
}
@Bean
public MessageConverter messageConverter() {
MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();
messageConverter.setTargetType(MessageType.TEXT);
messageConverter.setTypeIdPropertyName("_type");
return messageConverter;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个消息驱动的POJO,它监听给定的事件:
@JmsListener(destination = "events")
public void applicationSubmitted(MyType event) {
// do some work with the event here
jmsTemplate.convertAndSend("commands", mymessage);
}
Run Code Online (Sandbox Code Playgroud)
还有一个:
@JmsListener(destination = "commands")
public void onCommand(TextMessage textMessage) {
}
Run Code Online (Sandbox Code Playgroud)
我试过的一件事就是添加一个延迟,即sleep(200)在发送消息之后.然而,这是非常不可靠的,也会减慢测试速度,因为执行可能需要不到50毫秒.以下是测试本身.除非等待取消注释,否则我永远不会进入第二个事件监听器,因为应用程序上下文关闭,测试结束并且消息被"遗忘".
@SpringBootTest
class MyEventIntegrationTest extends Specification {
@Autowired
JmsTemplate jmsTemplate
def "My event is successfully handled"() {
given:
def event = new MyEvent()
when:
jmsTemplate.convertAndSend("events", event)
// sleep(200)
then:
1 == 1
}
}
Run Code Online (Sandbox Code Playgroud)
我认为你的问题的根源是异步事件处理。发送事件后,您的测试就结束了。当然,这将导致 Spring 上下文和代理关闭。JMS 侦听器正在另一个线程中运行。你必须想办法等待他们。否则,您的线程(即您的测试用例)就刚刚完成。
我们在上一个项目中遇到了类似的问题,并编写了一个小实用程序,这对我们有很大帮助。JMS 提供“浏览”队列并查看队列是否为空的功能:
public final class JmsUtil {
private static final int MAX_TRIES = 5000;
private final JmsTemplate jmsTemplate;
public JmsUtil(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
private int getMessageCount(String queueName) {
return jmsTemplate.browseSelected(queueName, "true = true", (s, qb) -> Collections.list(qb.getEnumeration()).size());
}
public void waitForAll(String queueName) {
int i = 0;
while (i <= MAX_TRIES) {
if (getMessageCount(queueName) == 0) {
return;
}
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个实用程序,您可以执行以下操作:
def "My event is successfully handled"() {
given:
def event = new MyEvent()
when:
jmsTemplate.convertAndSend("events", event)
jmsUtility.waitForAll("events"); // wait until the event has been consumed
jmsUtility.waitForAll("commands"); // wait until the command has been consumed
then:
1 == 1
}
Run Code Online (Sandbox Code Playgroud)
注意:此实用程序假定您将 JMS 消息发送到队列。通过浏览队列我们可以检查它是否为空。如果是某个主题,您可能需要进行另一次检查。所以要注意这一点!
| 归档时间: |
|
| 查看次数: |
689 次 |
| 最近记录: |