问题描述
嗨,我使用测试容器对 docker 进行了集成测试。在容器上我运行 jms。在测试中,我将消息放入队列中。
我如何在测试中等待以使其填充到 jms 上?
在本地机器上它可以工作,但在 jenkins 上它失败了,所以我必须添加
Thread.sleep(3000);
但这很讨厌。 org.awaitility 似乎错过了用法:
await().atMost(2,TimeUnit.SECONDS).until(() -> return true));
我只需要暂停一下就可以让 jms 传播(放在 jms 队列中)并等待侦听器采取行动,这就是将消息放入数据库。 然后我必须调用 get rest 端点来查看它是否有效。
使用主题会更容易,因为我会在主题上创建测试侦听器。 但它是队列,可以在监听器上获取消息。
预先感谢您的任何建议
解决方法
将 org.awaitility
与 JMS QueueBrowser 一起使用,例如:
@Test
public void myTest() throws Exception {
...
await().atMost(2,TimeUnit.SECONDS).until(() -> return queueIsEmpty(queueName)));
...
}
private boolean queueIsEmpty(String queueName) {
ConnectionFactory cf = new MyBrokersConnectionFactory();
Connection connection = cf.createConnection();
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
QueueBrowser browser = session.createBrowser(session.createQueue(queueName));
Enumeration enumeration = senderBrowser.getEnumeration();
while (enumeration.hasMoreElements()) {
return false;
}
return true;
}
QueueBrowser
是只读,因此没有实际消耗消息的危险。
另一个可能的选择是创建一个具有事务处理会话的消费者,然后尝试接收消息。如果您确实收到了一条消息,您可以回滚事务并关闭消费者。
,使用重试(例如 Spring RetryTemplate 或 Failsafe Retry Policy)来缩短集成测试执行时间:
- 重试 SQL 查询,直到记录出现
- 重试 REST 端点,直到成功
这里是一个等待数据库记录的例子;根据您的需要调整政策:
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(new FixedBackOffPolicy());
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(
10,Collections.singletonMap(AssertionError.class,true)));
retryTemplate.execute(retryContext -> {
List<MyRecord> records = jdbcTemplate.query("select ...");
Assert.assertEquals(1,records.size());
return null;
});
,
我的解决方案是使用 org.awaitility
库并用返回语句替换断言:
await().atMost(30,TimeUnit.SECONDS).until(
() -> {
//
// assertTrue(condition);
return condition == true;
}