Running with Spring Boot v2.3.4.RELEASE, Spring v5.2.9.RELEASE, JUnit5, IBM MQ
I am writing an integration @SpringBootTest that tests a MessageListener.
The test creates random named queues in order to keep build pipeline distinct.
Currently the @BeforeAll Tests creates these queues and attempts to modify the Destination Name in the DefaultMessageListenerContainer Bean. It appears you can't do this before all tests since the spring container has already created the MessageListnerContainer and ignores a change in the container.
@EnableJms
@Configuration
public class JmsConfig {
@Autowired
private Environment env;
@Value("${inbound-queue}")
private String inboundQueue;
@Bean
public MQConnectionFactory mqConnectionFactory() throws JMSException {
MQConnectionFactory connectionFactory = new MQConnectionFactory();
connectionFactory.setHostName(env.getProperty("mq.hostname")); //mq host name
connectionFactory.setPort( Integer.parseInt(env.getProperty("mq.port"))); // mq port
connectionFactory.setQueueManager(env.getProperty("mq.manager")); //mq queue manager
connectionFactory.setChannel(env.getProperty("mq.channel")); //mq channel name
connectionFactory.setTransportType(1); //WMQConstants.WMQ_CM_CLIENT
return connectionFactory;
}
@Bean
public DefaultMessageListenerContainer mqMessageEventContainer() throws JMSException {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setAutoStartup(true);
container.setConnectionFactory(mqConnectionFactory());
container.setDestinationName(inboundQueue);
container.setMessageListener(new NotificationListener());
return container;
}
Listener:
@Slf4j
public class NotificationListener implements MessageListener {
@Override
@Transactional()
public void onMessage(Message msg) {
log.debug("Received a {}", msg.getClass().getSimpleName());
try {
if (msg instanceof JMSObjectMessage) {
JMSObjectMessage bmrMsg = (JMSObjectMessage) msg;
log.debug("bmrMsg is a " + bmrMsg.getObject().getClass().getSimpleName());
The test:
@Autowired
private JmsConfig jmsConfig;
@BeforeAll
public void beforeAllTests(TestInfo testInfo) {
log.info(START_TEST + testInfo.getTestMethod());
buildTempQueues();
log.info(END_TEST + testInfo.getTestMethod());
}
private void buildTempQueues() {
assertThat(qHost).isNotNull();
assertThat(qPortString).isNotNull();
assertThat(qMgr).isNotNull();
assertThat(qChannel).isNotNull();
buildTempQueues(qHost, qPortString, qMgr, qChannel);
Optional<String> qOpt = getQueueName(INBOUND_QUEUE_ENDING);
if (qOpt.isPresent()) {
String ibQueue = qOpt.get();
ReflectionTestUtils.setField(jmsConfig, "inboundQueue", ibQueue);
try {
jmsConfig.mqMessageEventContainer().setDestinationName(ibQueue);
} catch (JMSException e) {
fail(e.getMessage());
}
} else {
fail("COULD NOT CONFIGURE QUEUES FOR TESTING");
}
qOpt = getQueueName(FAILURE_QUEUE_ENDING);
if (qOpt.isPresent()) {
ReflectionTestUtils.setField(jmsService, "failureQueue", qOpt.get());
}
}
jmsConfig.mqMessageEventContainer().setDestinationName(ibQueue);
So jmsConfig.mqMessageEventContainer().setDestinationName(ibQueue); does not appear to change the Bean since the Spring context has already created the listener....
final CountDownLatch latch = new CountDownLatch(1);
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
//then
jmsTemplate.convertAndSend(getQueueName(INBOUND_QUEUE_ENDING).get(), givenScript.getSubject());
PCFMessage[] responses = getQueueDepth(qHost, qPortString, qMgr, qChannel, INBOUND_QUEUE_ENDING);
assertThat(responses).isNotNull();
for (PCFMessage response : responses) {
assertThat(0).isEqualTo(response.getCompCode());
assertThat(getQueueName(INBOUND_QUEUE_ENDING).get()).isEqualTo(trim(response.getStringParameterValue(MQConstants.MQCA_Q_NAME)));
assertThat(1).isEqualTo(response.getIntParameterValue(MQConstants.MQIA_CURRENT_Q_DEPTH));
}
while (notificationService.getMsgCt() == 0) {
Thread.sleep(2000);
log.debug("Messages processed = " + notificationService.getMsgCt());
}
// now signal that our background task completed
latch.countDown();
} catch (JmsException | PCFException | InterruptedException e) {
fail(e.getMessage());
}
});
log.info("(T) waiting on latch...");
try {
// Block the test thread for at most 5 seconds before giving up and failing the test.
boolean receivedSignal = latch.await(15, TimeUnit.SECONDS);
log.info(String.format("(T) Test thread did wait on latch (timeout=%b)", !receivedSignal));
assertThat(receivedSignal).isTrue();
//TODO Test outboud queue has depth 1
} catch (InterruptedException e) {
fail(e.getMessage());
}
LOGS:
12:42:49.876 [main] INFO g.d.t.v.v.v.s.i.NotificationListenerTests.whenOnMessage_givenMessageOnQueue_thenProcessMessage - (T) waiting on latch...
12:42:52.102 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:42:54.102 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:42:56.103 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:42:58.103 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:43:00.103 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:43:02.104 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:43:04.105 [pool-3-thread-1] DEBUG g.d.t.v.v.v.s.i.NotificationListenerTests.lambda$whenOnMessage_givenMessageOnQueue_thenProcessMessage$0 - Messages processed = 0
12:43:04.879 [main] INFO g.d.t.v.v.v.s.i.NotificationListenerTests.whenOnMessage_givenMessageOnQueue_thenProcessMessage - (T) Test thread did wait on latch (timeout=true)
ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 33.779 s <<< FAILURE! - in gov.dhs.tsa.vcs.vet.vcsn.service.impl.NotificationListenerTests
[ERROR] whenOnMessage_givenMessageOnQueue_thenProcessMessage{TestInfo} Time elapsed: 15.723 s <<< FAILURE!
org.opentest4j.AssertionFailedError:
Expecting:
<false>
to be equal to:
<true>
but was not.
question from:
https://stackoverflow.com/questions/65602919/springboottest-how-to-modify-defaultmessagelistenercontainer-in-integration-te