2017-02-15 44 views
0

Как я могу предотвратить SpringJmsTemplate unit test sendAndReceivePerson() от блокировки при попытке прочитать Person объект от ActiveMQ queue person.queue?Как я могу предотвратить блокировку тестового блока Spring JmsTemplate при чтении очереди ActiveMQ?

Тест создает объект 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

Печально известная проблема при тестировании со встроенным брокером.

Соединение закрывается между операциями и, без сохранения данных, данные теряются.

Попробуйте обернуть завод по подключению в CachingConnectionFactory, чтобы соединение оставалось открытым (и, следовательно, брокер остается включенным).

В любом случае вы должны использовать CachingConnectionFactory с JmsTemplate по соображениям производительности, но это особенно плохо в модульном тесте.

+0

Вы абсолютно правы! Я наткнулся на пример в Github, который завернул «ConnectionFactory» в «CachingConnectionFactory», и с этим изменением мой тест прошел и вывел только одно предупреждение о памяти «BrokerService». Теперь, чтобы решить это предупреждение ... –

+0

Для чего это стоит, https://github.com/lex-alpha7/bank_account/blob/master/jms/src/main/java/com/ostdlabs/bank_account/jms/config/ JMSSpringConfig.java - это пример, который я нашел, который демонстрирует, как обернуть 'ConnectionFactory' в' CachingConnectionFactory'. –

0

В Gary Russellsuggested, с тем чтобы предотвратить каждую операцию 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 
------------------------------------------------------------------------ 

 Смежные вопросы

  • Нет связанных вопросов^_^