In the code snippet I am testing, there is a simple queue that gets periodically emptied. Each number in the queue triggers an HTTP POST request to send it to a fictional API address. If the POST is successful, the number is removed from the queue and the next number is processed.
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;
if (this.queue.length !== 0) {
const item = this.queue[0];
this.postNumber(item)
.then(
() => {
this.queue.shift();
this.processQueue();
},
() => {
this.processingQueue = false;
}
);
} else {
this.processingQueue = false;
}
}
enqueue(number: number): void {
this.queue.push(number);
}
}
The test I aim to conduct will confirm that after adding three items to the queue, calling processQueue()
once will empty it.
An example using 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();
// include waiting logic for processQueue() completion
expect(queueService.queue.length).toBe(0);
});
});
However, the second expect()
fails with the message Expected 3 to be 0
. This is likely due to the asynchronous nature of the promises returned by postNumber()
, causing the queue not to be empty when the second expectation is evaluated.
How can I ensure that processQueue()
completes before checking whether the queue has been emptied?