У меня есть приложение 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);
});
});
Вместо того, чтобы просто ждать произвольное ограничение по времени, прежде чем я проверю, существует ли запись, есть ли лучший способ структурировать этот тест?
Или определенное время ожидания полностью соответствует функциональности, управляемой событиями?