我有以下队列使用者类,它通过promises递送运行:
"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;
我已经定义了一个测试,它基本上断言正确的工作流程正在发生,并且消费者最终处理队列中的所有任务(这是在真正的Redis代理之前工作的集成测试)
测试:
"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()
,但根本不起作用(测试似乎没有等待,消费者类中的超时未触发);
预期行为:callCount
为NUM_OF_ITEMS
(通过递归调用)。
实际行为:callCount
始终为1。
答案 0 :(得分:1)
Hi it's a little confusing to understand what your queue class is doing. Is it a singleton?
If it's not a singleton your consumer is initialised with a fresh empty queue on construction.
function Consumer() {
this.queue = new queue.TaskQueue();
...
}
...
describe("success callback", function () {
before(function () {
consumerInstance = new consumer.Consumer();
spy = sinon.spy(consumerInstance, "queueSuccessFb");
});
....
This won't be the same as the queue you created in
describe("task handling", function () {
beforeEach(function (done) {
...
queueInstance = new queue.TaskQueue();
...
});
...
And as the queues are not the same spy.callCount !== NUM_OF_ITEMS
Unless of course it's a singleton ie:
new queue.TaskQueue() === new queue.TaskQueue();
My suggestion is to enable the TaskQueue to be supplied to the Consumer constructor so you know that the consumer is operating over the expected queue
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");
});
....