We currently are trying to test our angular services which use promises to return values to the controllers. The issue is that the functions we attach to the .then do not get called in Jasmine.
We found that adding $rootScope.digest() to the function after the promise is returned allows synchronous promises to be called however it still does not work for Asynchronous promises.
The code so far is
beforeEach(inject(function (Service, $rootScope)
{
service = Service;
root = $rootScope;
}));
it('gets all the available products', function (done)
{
service.getData().then(function (data)
{
expect(data).not.toBeNull();
expect(data.length).toBeGreaterThan(0);
done();
});
root.$digest();
});
In this case the promise gets called fine but if it is asynchronous it will not be called because the promise is not ready for "digestion" by the time the root.$digest() is called.
Is there some way to tell when a promise is after getting resolved so that i can call digest? Or maybe something that would do that automatically? Thanks ;)
Partial of the Service we must test(error handling removed):
var app = angular.module('service', []);
/**
* Service for accessing data relating to the updates/downloads
* */
app.factory('Service', function ($q)
{
... init
function getData()
{
var deffered = $q.defer();
var processors = [displayNameProc];
downloads.getData(function (err, data)
{
chain.process(processors, data, function (err, processedData)
{
deffered.resolve(processedData);
});
});
return deffered.promise;
}
...
In the case where there is a problem is when service.getData is async the promise is resolved but the function attached to that promise from the test code is not called because the root.$digest has already been called. Hope this gives more info
Workaround
var interval;
beforeEach(inject(function ($rootScope)
{
if(!interval)
{
interval = function ()
{
$rootScope.$digest();
};
window.setInterval(interval, /*timing*/);
}
}));
I ended up using the workaround above to call the digest repeatedly so each layer of promise would get a chance to run...its not ideal or pretty but it works for the test...