如何在集成测试中等待某些操作

问题描述

嗨,我使用测试容器对 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 RetryTemplateFailsafe 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;
            }