Home > Software design >  NodeJS Unit Test RabbitMQ / Amqplib
NodeJS Unit Test RabbitMQ / Amqplib

Time:10-28

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.

  • Related