下面是我要测试的代码的简化版本:一个定期清空的简单队列。对于队列中的每个号码,都会进行HTTP POST以将其发送到(在此示例中为虚构的)API地址。如果POST成功,则该号码将从队列中移出,并考虑下一个号码。
class Queue {
queue: Array<number>;
processingQueue: boolean;
constructor(public $http: angular.IHttpService) {
this.queue = new Array<number>();
this.processingQueue = false;
}
startQueueProcessor() {
this.processingQueue = false;
setInterval(() => {
if (!this.processingQueue)
this.processQueue();
}, 1000);
}
postNumber(number: number): angular.IHttpPromise<{}> {
return this.$http.post('http://mydummyurl.com/givemeanumber', number);
}
processQueue(): void {
this.processingQueue = true; // we are currently processing a queue, so make sure setInterval does not trigger another processing run
if (this.queue.length !== 0) { // are there any numbers to deal with?
const item = this.queue[0]; // get the first number in the queue
this.postNumber(item) // POST it (returns a promise)
.then(
() => { // if successful...
this.queue.shift(); // we've dealt with this item, so remove it from the queue
this.processQueue(); // check the queue again (recurses until all items have been dealt with)
},
() => { // if unsuccessful...
this.processingQueue = false; // something went wrong, so stop
}
);
} else {
this.processingQueue = false; // queue is empty, stop processing
}
}
enqueue(number: number): void { // add a number to the queue
this.queue.push(number);
}
}
我想要创建的测试将检查,在将三个项目添加到队列后,对processQueue()
的单个调用将清空它。
像这样(在Jasmine中嘲笑):
describe('queueing', () => {
var queueService;
beforeEach(inject((_$httpBackend_, $injector) => {
httpBackend = _$httpBackend_;
httpBackend.whenPOST().respond(200);
queueService = $injector.get('queue');
}));
it('should clear queue completely when processQueue() is called once', () => {
queueService.enqueue(1);
queueService.enqueue(2);
queueService.enqueue(3);
expect(queueService.queue.length).toBe(3);
queueService.processQueue();
// somehow wait for processQueue() to complete
expect(queueService.queue.length).toBe(0);
});
});
我的问题是第二个expect()
始终失败并显示消息Expected 3 to be 0
。我假设这是由于postNumber()
没有等待返回的promise,因此在第二个expect()
被调用时队列不为空。
在尝试断言队列已清空之前,如何等待processQueue()
完成?
答案 0 :(得分:0)
您应该修改processQueue以返回Promise。最简单的方法是使用async
关键字标记方法,然后使用await
:
async processQueue(): Promise<void>
{
this.processingQueue = true; // we are currently processing a queue, so make sure setInterval does not trigger another processing run
if (this.queue.length !== 0)
{ // are there any numbers to deal with?
const item = this.queue[0]; // get the first number in the queue
try
{
await this.postNumber(item); // POST it (returns a promise)
// if successful...
this.queue.shift(); // we've dealt with this item, so remove it from the queue
this.processQueue(); // check the queue again (recurses until all items have been dealt with)
}
catch
{
this.processingQueue = false; // something went wrong, so stop
}
}
else
{
this.processingQueue = false; // queue is empty, stop processing
}
}
然后在你的测试中:
it('should clear queue completely when processQueue() is called once', async (done) => {
queueService.enqueue(1);
queueService.enqueue(2);
queueService.enqueue(3);
expect(queueService.queue.length).toBe(3);
await queueService.processQueue();
// somehow wait for processQueue() to complete
expect(queueService.queue.length).toBe(0);
done();
});
希望这有帮助。