测试依赖于回调返回的对象的函数调用

时间:2015-12-23 16:57:16

标签: node.js testing rabbitmq amqp

我想测试以下代码:

'use strict';

const amqp = require('amqplib');
const Promise = require('bluebird');

const queueManager = function queueManager() {
  const amqp_host = 'amqp://' + process.env.AMQP_HOST || 'localhost';

  return {
    setupQueue: Promise.method(function setupQueue(queue) {
      return amqp.connect(amqp_host)
        .then(conn => conn.createConfirmChannel())
        .tap(channel => channel.assertQueue(queue));
    }),
    enqueueJob: Promise.method(function enqueueJob(channel, queue, job) {
      return channel.sendToQueue(queue, new Buffer(job));
    }),
    consumeJob: Promise.method(function consumeJob(channel, queue) {
      return channel.consume(queue, msg => msg);
    })
  };
};

module.exports = {
  create: queueManager
}

我想测试我的setupQueueenqueueJobconsumeJob方法,以确保他们为AMQP服务器做正确的事情。

例如,对于setupQueue,我想确保它使用Channel.createConfirmChannel代替Channel.createChannel,而且Channel.assertQueue也是如此。

但是,我不知道该怎么做。

如果我使用proxyquire模拟amqp变量,我将能够监视的是amqp.connect调用。我可能会将其存根以避免命中任何AMQP服务器。但是下面的陈述呢?如何使用connchannel对象?

1 个答案:

答案 0 :(得分:0)

我建议使用依赖注入模式。

在我看来,依赖注入是轻松进行单元测试的黄金票。这不仅适用于此特定测试,而且适用于您正在编写的所有测试。

要完成此任务,您必须

  1. 拆分方法
  2. 在这些方法中使用依赖注入
  3. 也许让queueManager的构造函数访问连接
  4. 使用SinonJs库来存根/模拟/间谍。
  5. 它看起来像这样

    
    
    var channelFactory = (conn) => conn.createConfirmChannel();
    
    function QueueManager(queue, channelFactory){
      this.queue = queue;
      this.channelFactory = channelFactory;
    }
    
    QueueManager.prototype.setupQueue = () => 
        (var scope = this)
          .channelFactory()
          .then((channel) => (scope.channel = channel).assertQueue(scope.queue);
    
    QueueManager.enqueueJob = (channel, queue, job) => channel.sendToQueue(queue, new Buffer(job));
    QueueManager.consumeJob = (channel, queue) => channel.consume(queue, msg => msg);
    
    // Unit tests
    
    describe('setupQueue', () => {
      it('should do smth', (done) => {
        
        var host            = 'localhost',
            conn            = new connection(host),
            queue           = new queue(),
            aChannelFactory = channelFactory.bind(queue, conn),
            queueManager    = new QueueManager(queue, aChannelFactory),
            spy             = sinon.spy(channel.conn, 'createConfirmChannel');
        
        queueManager
          .setupQueue()
          .then(()    => { assert.spy.calledOnce(); done(); })
          .fail((err) => { done(err); })
          .finally(() => { spy.restore(); })
      })
    })