У меня довольно стандартная настройка, связанная с JMS
- Spring Boot
и ActiveMQ
. Он отлично работает, пока я не попытался выполнить простой интеграционный тест. После некоторого расследования я обнаружил, что и контекст Spring, и встроенный брокер закрыты после того, как первое сообщение JMS было израсходовано, независимо от того, что во время потребления происходит другое событие. Проблема брокера, которую я смог решить, добавив параметр useShutdownHook=false
connection в тестовую настройку, то есть
spring.activemq.broker-url = vm://broker?async=false&broker.persistent=false&broker.useShutdownHook=false
То, что я ищу, в основном является способом заставить тест "остаться в живых" до тех пор, пока все сообщения 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;
}
}
Затем я получаю POJO с сообщением, который прослушивает данное событие:
@JmsListener(destination = "events")
public void applicationSubmitted(MyType event) {
// do some work with the event here
jmsTemplate.convertAndSend("commands", mymessage);
}
И еще один:
@JmsListener(destination = "commands")
public void onCommand(TextMessage textMessage) {
}
Одна вещь, которую я опробовал, и это сработало, - это добавить задержку, то есть 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
}
}