NodeJS 单元测试 RabbitMQ / Amqplib
NodeJS Unit Test RabbitMQ / Amqplib
我正在尝试为我的项目开发测试,我有一个连接到 rabbitmq 并使用队列的文件,但我在想测试它时遇到问题
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;
可以测试这个文件吗?我如何使用 JEST 或任何其他库来做到这一点?
您可以使用 jest.spyOn(object, methodName) 为 amqp
对象的方法创建模拟。
使用jest.useFakeTimers(implementation?: 'modern' | 'legacy')告诉jest使用setTimeout
函数的假版本,这样你就不需要等待真正的延迟时间。
使用jest.advanceTimersByTime(msToRun)到
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
例如
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 });
});
});
测试结果:
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
您可以创建模拟错误并将它们传递给模拟实现的 callback
以测试错误处理程序分支。
我正在尝试为我的项目开发测试,我有一个连接到 rabbitmq 并使用队列的文件,但我在想测试它时遇到问题
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;
可以测试这个文件吗?我如何使用 JEST 或任何其他库来做到这一点?
您可以使用 jest.spyOn(object, methodName) 为 amqp
对象的方法创建模拟。
使用jest.useFakeTimers(implementation?: 'modern' | 'legacy')告诉jest使用setTimeout
函数的假版本,这样你就不需要等待真正的延迟时间。
使用jest.advanceTimersByTime(msToRun)到
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
例如
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 });
});
});
测试结果:
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
您可以创建模拟错误并将它们传递给模拟实现的 callback
以测试错误处理程序分支。