I have an angular service that has an async dependency like this
(function() {
angular
.module('app')
.factory('myService', ['$q', 'asyncService',
function($q, asyncService) {
var myData = null;
return {
initialize: initialize,
};
function initialize(loanId){
return asyncService.getData(id)
.then(function(data){
console.log("got the data!");
myData = data;
});
}
}]);
})();
I want to unit test the initialize function and I'm trying in jasmine like this:
describe("Rate Structure Lookup Service", function() {
var $q;
var $rootScope;
var getDataDeferred;
var mockAsyncService;
var service;
beforeEach(function(){
module('app');
module(function ($provide) {
$provide.value('asyncService', mockAsyncService);
});
inject(function(_$q_, _$rootScope_, myService) {
$q = _$q_;
$rootScope = _$rootScope_;
service = myService;
});
getDataDeferred = $q.defer();
mockAsyncService = {
getData: jasmine.createSpy('getData').and.returnValue(getDataDeferred.promise)
};
});
describe("Lookup Data", function(){
var data;
beforeEach(function(){
testData = [{
recordId: 2,
effectiveDate: moment("1/1/2015", "l")
},{
recordId: 1,
effectiveDate: moment("1/1/2014", "l")
}];
});
it("should get data", function(){
getDataDeferred.resolve(testData);
service.initialize(1234).then(function(){
console.log("I've been resolved!");
expect(mockAsyncService.getData).toHaveBeenCalledWith(1234);
});
$rootScope.$apply();
});
});
});
None of the console messages appear and the test seems to just fly on through without the promises ever being resolved. I though that the $rootScope.$apply() would do it but seems not to.
UPDATE
@estus was right that $rootScope.$appy() is sufficient to trigger resolution of all the promises. It seems that the issue was in my mocking of the asyncService. I changed it from
mockAsyncService = {
getData: jasmine.createSpy('getData').and.returnValue(getDataDeferred.promise)
};
to
mockAsyncService = {
getData: jasmine.createSpy('getData').and.callFake(
function(id){
return $q.when(testData);
})
};
and I set testData to what I need to for the tests rather than calling getDataDeferred.resolve(testData). Prior to this change, the mockAsyncService was being injected but the promise for getDataDeferred was never being resolved.
I don't know if this is something in the order of injection in the beforeEach or what. Even more curious was that is has to be a callFake. Using .and.returnValue($q.when(testData)) still blocks promise resolution.