【问题标题】:NodeJS Unit Test RabbitMQ / AmqplibNodeJS 单元测试 RabbitMQ / Amqplib
【发布时间】:2021-10-26 20:04:24
【问题描述】:

我正在尝试为我的项目开发测试,并且我有一个连接到 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 或任何其他库来做到这一点?

【问题讨论】:

    标签: node.js unit-testing rabbitmq tdd ts-jest


    【解决方案1】:

    您可以使用jest.spyOn(object, methodName)amqp 对象的方法创建模拟。

    使用jest.useFakeTimers(implementation?: 'modern' | 'legacy') 告诉 jest 使用了伪造版本的setTimeout 函数,这样您就无需等待真正的延迟时间。

    使用jest.advanceTimersByTime(msToRun)

    调用此 API 时,所有计时器都会提前 msToRun 毫秒。所有已通过 setTimeout() 或 setInterval() 排队的待处理“宏任务”将在此时间范围内执行

    例如

    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 以测试错误处理程序分支。

    【讨论】:

    • 谢谢你!很好的解释!
    • 精彩的答案@slideshowp2。谢谢!
    猜你喜欢
    • 2019-10-25
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2018-10-01
    • 2011-08-23
    相关资源
    最近更新 更多