I have a pretty standard setup related to JMS
- Spring Boot
and ActiveMQ
. It works fine, until i tried to do a simple integration test. After some investigation I found that both the Spring context and the embedded broker are closed after the first JMS message has been consumed, no matter that during the consumption, another event is fired. The broker issue i was able to solve by adding the useShutdownHook=false
connection option in the test setup, i.e.
spring.activemq.broker-url = vm://broker?async=false&broker.persistent=false&broker.useShutdownHook=false
What i'm looking for is basically a way to force the test to "stay alive" until all JMS messages are consumed (in this case they are just two). I understand the async nature of the whole setup, but still during tests it would be helpful to get all the results of these messages being produced and consumed.
Below is my setup, although it's fairly simple.
@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;
}
}
I then have a message-driven POJO that listens for a given event:
@JmsListener(destination = "events")
public void applicationSubmitted(MyType event) {
// do some work with the event here
jmsTemplate.convertAndSend("commands", mymessage);
}
And another one:
@JmsListener(destination = "commands")
public void onCommand(TextMessage textMessage) {
}
One thing that I tried out and it worked is to add a delay, i.e. sleep(200)
after the message is sent. However, that's very unreliable and also slows down tests, as the execution perhaps takes less that 50ms. Below's the test itself. Unless the waiting is uncommented, i never get to the second event listener, as the application context closes, the tests ends and the message is "forgotten".
@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
}
}