I am trying to develop tests for my project and I have a file that connects to rabbitmq and consumes a queue, but i'm having problems to have idea to test it
const amqp = require('amqplib/callback_api');
const rabbitConsumer = (io) => {
setTimeout(() => {
amqp.connect('amqp://rabbitmq', (error0, connection) => {
if (error0) {
throw error0;
}
connection.createChannel((error1, channel) => {
if (error1) {
throw error1;
}
const queue = 'message';
channel.assertQueue(queue, {
durable: false,
});
console.log(' [*] Waiting for message', queue);
channel.consume(
queue,
(data) => {
console.log(' [x] Received data:', data.content.toString('utf-8'));
io.emit('sendMessage', data.content.toString('utf-8'));
},
{
noAck: true,
}
);
});
});
}, 10000);
};
module.exports = rabbitConsumer;
Is possible to test this file? How could I do this using JEST or any other library?
CodePudding user response:
You can use jest.spyOn(object, methodName) to create mock for amqp
object's methods.
Use jest.useFakeTimers(implementation?: 'modern' | 'legacy') to tell jest uses fake versions of setTimeout
function so that you don't need to wait for real delay time.
Use jest.advanceTimersByTime(msToRun) to
When this API is called, all timers are advanced by msToRun milliseconds. All pending "macro-tasks" that have been queued via setTimeout() or setInterval(), and would be executed within this time frame will be executed
E.g.
index.js
:
const amqp = require('amqplib/callback_api');
const rabbitConsumer = (io) => {
setTimeout(() => {
amqp.connect('amqp://rabbitmq', (error0, connection) => {
if (error0) {
throw error0;
}
connection.createChannel((error1, channel) => {
if (error1) {
throw error1;
}
const queue = 'message';
channel.assertQueue(queue, { durable: false });
console.log(' [*] Waiting for message', queue);
channel.consume(
queue,
(data) => {
console.log(' [x] Received data:', data.content.toString('utf-8'));
io.emit('sendMessage', data.content.toString('utf-8'));
},
{ noAck: true }
);
});
});
}, 10000);
};
module.exports = rabbitConsumer;
index.test.js
:
const amqp = require('amqplib/callback_api');
const rabbitConsumer = require('./');
describe('rabbitConsumer', () => {
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
test('should pass', () => {
const mData = {
content: 'teresa teng',
};
const mChannel = {
assertQueue: jest.fn(),
consume: jest.fn().mockImplementation((queue, callback) => {
callback(mData);
}),
};
const mConnection = {
createChannel: jest.fn().mockImplementation((callback) => {
callback(null, mChannel);
}),
};
jest.spyOn(amqp, 'connect').mockImplementation((url, callback) => {
callback(null, mConnection);
});
const mIO = {
emit: jest.fn(),
};
rabbitConsumer(mIO);
jest.advanceTimersByTime(10000);
expect(amqp.connect).toBeCalledWith('amqp://rabbitmq', expect.any(Function));
expect(mConnection.createChannel).toBeCalledWith(expect.any(Function));
expect(mChannel.assertQueue).toBeCalledWith('message', { durable: false });
expect(mChannel.consume).toBeCalledWith('message', expect.any(Function), { noAck: true });
});
});
test result:
PASS examples/69715530/index.test.js (21.564 s)
rabbitConsumer
✓ should pass (27 ms)
console.log
[*] Waiting for message message
at examples/69715530/index.js:15:17
console.log
[x] Received data: teresa teng
at channel.consume.noAck (examples/69715530/index.js:19:21)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 87.5 | 50 | 100 | 87.5 |
index.js | 87.5 | 50 | 100 | 87.5 | 7,11
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 23.222 s
You can create mocked errors and pass them to the callback
of mock implementation to test the error handler branch.