在sinon中断言recursion调用的次数

我有以下队列消费者类通过承诺recursion运行:

"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; 

我已经定义了一个testing,它将基本上声明正确的工作stream正在发生,并且消费者最终处理队列中的所有任务(这是在真实的Redis代理前工作的集成testing)

testing:

 "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); }); }); }); }); 

我的问题是,调用计数总是等于1.我首先想到一个和andCallThrough()方法调用是必需的,类似于在Jasmine中的工作方式,但后来发现实际的函数正在被调用。

尝试使用sinon.useFakeTimers()但是根本没有工作(testing似乎没有等待,在消费类超时没有发射);

预期的行为: callCountNUM_OF_ITEMS (通过recursion调用)。 实际行为: callCount始终为1。

嗨,这是有点混淆理解你的队列正在做什么。 是单身吗?

如果不是一个单身人士,你的消费者将被初始化为一个新build的空队列。

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

这将不会与您创build的队列相同

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

和队列是一样的spy.callCount !== NUM_OF_ITEMS

当然,除非是单身人士,

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

我的build议是使TaskQueue被提供给消费者的构造函数,所以你知道消费者正在预期的队列

 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"); }); ....