How to resolve $q.all promises in Jasmine unit tests?
You can try putting $rootScope.$apply()
in an afterEach()
callback function. Promises resolve on $apply()
in Angular.
afterEach(function(){
rootScope.$apply();
});
Comments
-
Rahul R. over 3 years
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
withrootScope.$digest
. With q.all androotScope.$digest
(tried usingscope.$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 sayingexpected 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
. -
the_karel about 10 yearsIn case you wonder where's that documented: Differences between Kris Kowal's Q and $q & testing
-
Frank van Wijk about 9 years
$apply
usually gets a callback. I preferscope.$digest()
, which only digests the current scope, so has better performance. -
messerbill almost 9 yearsafterEach was enough for me. I just tested the promises inside of the afterEach() function and it worked. Ty man
-
Gabriel over 8 yearsI personally experience a wired behavior with this. I had 3 promises. Before adding afterEach...rootScope.$apply() no one works. After only one of them works.
-
Edward over 8 yearsDoes scope.digest resolve all promises? Even nested promises? Or do I need to call it multiple times to get the code to continue
-
pmont about 8 years@Edward - based on my experience, this doesn't resolve nested promises. I'd be grateful if someone would explain how to do so. In my case I'm using $q.all(). The first level of promises is resolved by $digest (or $apply), but the final success handler for the group of promises is never triggered.
-
Thomas Schultz about 8 years@pmont, you might have to add a code example but I think this might answer your question, stackoverflow.com/a/26224595/89702. You can pass in a list of the promises that you want to wait for and then run $apply at the end once everything is resolved.
-
Pat almost 8 yearsI was testing with jasmine v1 and had forgotten to enclose the code in a
runs
function (I also added awaits(1);
just prior) in order to run async. Once I did that,$rootScope.$digest();
worked as expected.