Rahul R. Rahul R. - 2 months ago 51
AngularJS Question

How to resolve $q.all promises in Jasmine unit tests?

My controller has code like below:

$q.all([qService.getData($scope.id), dService.getData(), qTService.get()])
.then(function (allData) {
$scope.data1 = allData[0];
$scope.data2 = allData[1];
$scope.data3 = allData[2];
});


And in my unit tests i am doing something like this:

beforeEach(inject(function($rootScope, $q, $location){// and other dependencies...
qServiceSpy = spyOn(_qService, 'getData').andCallFake(function () {
var data1 = {
id: 1,
sellingProperty: 1,
};
var d = $q.defer();
d.resolve(data1);
return d.promise;
});

dServiceSpy = spyOn(_dService, 'getData').andCallFake(function () {
var data2 = [{ "id": "1", "anotherProp": 123 }];
var d = $q.defer();
d.resolve(data2);
return d.promise;
});
qTServiceSpy = spyOn(_qTService, 'get').andCallFake(function () {
var data3 = [{ id: 0, name: 'Rahul' }];
var d = $q.defer();
d.resolve(data3);
return d.promise;
});
rootScope = $rootScope;
});


Now in my test i am checking if services are called and the data1, data2 are not undefined..

it('check if qService' got called, function() {
expect(scope.data1).toBeUndefined();
rootScope.$digest();
expect(_quoteService.getQuote).toHaveBeenCalled();
});
it('check if "data1" is defined', function () {
expect(scope.data1).toBeUndefined();
rootScope.$digest();
expect(scope.data1).toBeDefined();
});


my problem is, this was working fine until i replaced my individual service calls in controller with q.all and in tests
scope.$apply
with
rootScope.$digest
. With q.all and
rootScope.$digest
(tried using
scope.$apply
as well) both tests fails with error:


10 $digest() iterations reached. Aborting!


if i remove
rootScope.$digest
then the promises never get resolves and tests fails saying


expected undefined to be defined.


Any help how should i unit tests code with
q.all
?

came across this post

But that also doesn't help as i am already trying to use
$digest
.

Answer

You can try putting $rootScope.$apply() in an afterEach() callback function. Promises resolve on $apply() in Angular.

afterEach(function(){
    rootScope.$apply();
});