SpringBootTest - 如何在集成测试中修改 DefaultMessageListenerContainer
SpringBootTest - How to modify DefaultMessageListenerContainer in integration test
运行 Spring Boot v2.3.4.RELEASE, Spring v5.2.9.RELEASE, JUnit5, IBM MQ
我正在编写一个测试 MessageListener 的集成 @SpringBootTest。
测试创建随机命名队列以保持构建管道不同。
当前,@BeforeAll 测试创建这些队列并尝试修改 DefaultMessageListenerContainer Bean 中的目标名称。看来您不能在所有测试之前执行此操作,因为 spring 容器已经创建了 MessageListnerContainer 并忽略了容器中的更改。
@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;
}
听众:
@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());
测试:
@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);
所以jmsConfig.mqMessageEventContainer().setDestinationName(ibQueue);似乎没有更改 Bean,因为 Spring 上下文已经创建了侦听器....
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());
}
日志:
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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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.
在侦听器容器上将 autoStartup
设置为 false
。
自动将容器连接到测试用例中并设置其目的地;然后 start()
容器。
你不需要反射的东西 - 太晚了。
运行 Spring Boot v2.3.4.RELEASE, Spring v5.2.9.RELEASE, JUnit5, IBM MQ
我正在编写一个测试 MessageListener 的集成 @SpringBootTest。
测试创建随机命名队列以保持构建管道不同。 当前,@BeforeAll 测试创建这些队列并尝试修改 DefaultMessageListenerContainer Bean 中的目标名称。看来您不能在所有测试之前执行此操作,因为 spring 容器已经创建了 MessageListnerContainer 并忽略了容器中的更改。
@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;
}
听众:
@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());
测试:
@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);
所以jmsConfig.mqMessageEventContainer().setDestinationName(ibQueue);似乎没有更改 Bean,因为 Spring 上下文已经创建了侦听器....
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());
}
日志:
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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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[=14=] - 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.
在侦听器容器上将
autoStartup
设置为false
。自动将容器连接到测试用例中并设置其目的地;然后
start()
容器。你不需要反射的东西 - 太晚了。