Использование Mocha для тестирования интеграции обратного вызова, который должен срабатывать при получении сообщения AMQP, полученного - PullRequest
1 голос
/ 17 июня 2019

У меня есть приложение Feathers, которое использует RabbitMQ и пользовательскую оболочку amqplib для связи с другим кодом, выполняющимся в другом месте, и я изо всех сил пытаюсь написать хороший интеграционный тест, чтобы показать, что обратный вызов, который запускается при получении сообщения, работает правильно,Фактический обратный вызов просто принимает тело полученного сообщения и вызывает внутреннюю службу для помещения данных в базу данных.

У меня сервер RabbitMQ работает в тестовой среде, и идея заключалась в том, чтобы написать тест, которыйпубликует некоторые фиктивные данные для правильного обмена, а затем проверяет, что данные попадают в базу данных.Проблема в том, что я не могу понять, как сказать, что обратный вызов завершен, прежде чем я проверю базу данных.

Сейчас я просто публикую сообщение и затем использую тайм-аут, чтобы подождать несколько секунд, прежде чем проверятьбазы данных, но мне это не нравится, поскольку нет никакой гарантии, что обратный вызов будет завершен.

Код, который я тестирую, выглядит примерно так (не сам код, а просто пример):

const app = require('./app');

// handleAMQP is passed as a callback to the consumer
// it creates a new record in the myService database
const handleAMQP = async(message) => {
  await app.service('users').create(message.content);
};

// Subscribe takes an amqp connection, opens a channel, and connects a callback
const subscribe = (conn) => {
  let queue = 'myQueue';
  let exchange = 'myExchange';

  return conn.createChannel().then(function (ch) {
    var ok = ch.assertExchange(exchange, 'topic', { durable: true });

    ok = ok.then(function () {
      return ch.assertQueue(queue, { exclusive: true });
    });

    ok = ok.then(function (qok) {
      var queue = qok.queue;
      ch.bindQueue(queue, exchange, topic);
    });

    ok = ok.then(function (queue) {
      return ch.consume(queue, handleAMQP);
    });

  });

};

module.exports = {subscribe};

И мой тест выглядит примерно так:

const assert = require('assert');
const amqp = require('amqplib');

describe('AMQP Pub/Sub Tests', async () => {
  let exchange = 'myExchange';
  let topic = 'myTopic';

  let dummyData = {
    email: 'example@example.com',
    name: 'Example User'
  }

  it('creates a new db enry when amqp message recieved', async () => {
    // Publish some dummy data
    await amqp.connect('amqp://localhost').then((conn) => {
      conn.createChannel().then((ch) => {
        ch.assertExchange(exchange, 'topic', {durable: true}).then(() => {
          ch.publish(exchange, topic, dummyData).then(() => {
            ch.close();
          })
        });
      });
    });

    await setTimeout(() => { // Wait three seconds
      let result = app.service('users').find({email : 'example@example.com'}); // Attempt to find the newly created user
      assert.deepEqual(result.email, dummyData.email);
      assert.deepEqual(result.name, dummyData.name);
    }, 3000);
  });
});

Вместо того, чтобы просто ждать произвольное ограничение по времени, прежде чем я проверю, существует ли запись, есть ли лучший способ структурировать этот тест?

Или определенное время ожидания полностью соответствует функциональности, управляемой событиями?

...