2015-07-23 12 views
7

Ho la seguente classe di coda di consumatori, che corre in modo ricorsivo attraverso promesse:numero Assert di chiamate ricorsive in Sinon

"use strict"; 

var queue = require("./queue"), 
    helpers = require("./helpers"), 
    vendors = require("../config/vendors"), 
    queueConf = require("../config/queue"); 

function Consumer() { 
    this.queue = new queue.TaskQueue(); 
    this.currentItem = null; 
    this.port = null; 
    this.payload = null; 
} 

Consumer.prototype.payloadSuccessCb = function (data) { 
    this.payload = data; 
    this.run(); 
}; 

Consumer.prototype.failureCb = function (data) { 
    console.error(data); 
    throw new Error(data); 
    //TODO: Continue queue processing despite the error 
}; 

Consumer.prototype.processItem = function (data) { 
    this.currentItem = data; 
    process.send("Proccess " + process.pid + " is processing item " + this.currentItem); 
    helpers.getPayload(this.currentItem).then(this.payloadSuccessCb, this.failureCb); 
}; 

Consumer.prototype.wait = function() { 
    var self = this; 
    process.send("Proccess " + process.pid + " is waiting for new items"); 
    setTimeout(function() { 
     self.run(); 
    }, queueConf.waitTime); 
}; 

Consumer.prototype.queueSuccessFb = function (data) { 
    console.error("here"); 
    if (data) { 
     this.processItem(data); 
    } else { 
     this.wait(); 
    } 
}; 

Consumer.prototype.run = function() { 
    //this.port = helpers.getVendorPortById(this.currentItem); 
    this.queue.pop().then(this.queueSuccessFb, this.failureCb); 
}; 

exports.Consumer = Consumer; 

ho definito un test che sarà essenzialmente affermare che il flusso di lavoro corretto che sta accadendo, e che il consumatore in ultima analisi, gestisce tutte le attività in coda (si tratta di un test di integrazione che lavora di fronte a un vero e proprio mediatore Redis)

prova:

"use strict"; 

var consumer = require("./../../src/consumer"), 
    queue = require("./../../src/queue"), 
    Q = require("Q"), 
    sinon = require("sinon"), 
    assert = require("assert"), 
    queueConf = require("./../../config/queue"), 
    NUM_OF_ITEMS = 5, 
    queueInstance, 
    spy, 
    consumerInstance; 

describe("consumer", function() { 
    beforeEach(function() { 
     queueInstance = new queue.TaskQueue(); 
    }); 


    describe("waiting for tasks while the queue is empty", function() { 
     describe("queue success call back", function() { 
      before(function() { 
       consumerInstance = new consumer.Consumer(); 
       spy = sinon.spy(consumerInstance, "queueSuccessFb"); 
      }); 

      it("should call the success callback once per the defined period", function (done) { 
       consumerInstance.run(); 
       setTimeout(function() { 
        sinon.assert.calledOnce(spy); 
        done(); 
       }, queueConf.waitTime); 
      }); 

      it("should call the success callback twice per the defined period + 1", function (done) { 
       consumerInstance.run(); 
       setTimeout(function() { 
        sinon.assert.calledTwice(spy); 
        done(); 
       }, queueConf.waitTime * 2); 
      }); 
     }); 

     describe("wait function", function() { 
      before(function() { 
       consumerInstance = new consumer.Consumer(); 
       spy = sinon.spy(consumerInstance, "wait"); 
      }); 
     }); 

    }); 

    describe("task handling", function() { 
     beforeEach(function (done) { 
      this.timeout(6000); 
      var i, promises = []; 
      queueInstance = new queue.TaskQueue(); 
      for (i = 1; i <= NUM_OF_ITEMS; i += 1) { 
       promises.push(queueInstance.push(i)); 
      } 
      Q.all(promises).then(function() { 
       done(); 
      }); 

     }); 

     afterEach(function() { 
      queueInstance.empty(); 
     }); 

     describe("sucess callback", function() { 
      before(function() { 
       consumerInstance = new consumer.Consumer(); 
       spy = sinon.spy(consumerInstance, "queueSuccessFb"); 
      }); 
      it("should run all of the available tasks one by one", function (done) { 
       this.timeout(6000); 
       consumerInstance.run(); 
       setTimeout(function() { 
        console.info(spy.callCount); 
        assert(spy.callCount === NUM_OF_ITEMS); 
        done(); 
       }, 2000); 
      }); 
     }); 
    }); 
}); 

mio il problema è che il conteggio delle chiamate è sempre uguale a 1. Inizialmente pensavo che fosse necessaria una chiamata al metodo andCallThrough(), simile a come funziona in Jasmine, ma poi ho scoperto che la funzione effettiva è stata invocata.

Provato usando sinon.useFakeTimers() ma che non ha funzionato affatto (il test non sembrava attendere, il timeout nella classe consumer non stava sparando);

Comportamento prevista: callCount è come NUM_OF_ITEMS (tramite chiamate ricorsive). Comportamento effettivo: callCount è sempre 1.

risposta

1

Ciao è un po 'di confusione per capire cosa sta facendo la tua classe di coda. È un singleton?

Se è non un singleton vostro consumatore viene inizializzato con una coda vuota fresca sulla costruzione.

function Consumer() { 
    this.queue = new queue.TaskQueue(); 
    ... 
} 
... 
    describe("success callback", function() { 
     before(function() { 
      consumerInstance = new consumer.Consumer(); 
      spy = sinon.spy(consumerInstance, "queueSuccessFb"); 
     }); 
     .... 

Questa non sarà la stessa della coda creata nel

describe("task handling", function() { 
    beforeEach(function (done) { 
     ... 
     queueInstance = new queue.TaskQueue(); 
     ... 
    }); 
    ... 

E come le code sono non lo stesso spy.callCount !== NUM_OF_ITEMS

A meno che, naturalmente, è un singleton es .:

new queue.TaskQueue() === new queue.TaskQueue(); 

Il mio suggerimento è di abilitare TaskQueue da fornire al costruttore Consumer in modo da sapere che l'utente sta operando sulla coda attesa

function Consumer(queue) { 
    this.queue = queue; 
    ... 
} 

describe("task handling", function() { 
    beforeEach(function (done) { 
     ... 
     this.queueInstance = new queue.TaskQueue(); 
     ... 
    }); 
    ... 

    describe("success callback", function() { 
     before(function() { 
      consumerInstance = new consumer.Consumer(this.queueInstance); 
      spy = sinon.spy(consumerInstance, "queueSuccessFb"); 
     }); 
     ....