In my controller, I have:
$scope.index = function() {
CompanyService.initialized.then(function() {
var company_id = CompanyService.getCompany()._id;
LocationService.list(company_id, $routeParams.location_parent_id).then(function(response) {
if(response.data.status === 'ok') {
$scope.locations = response.data.locations;
$scope.current_location = response.data.location || null;
}
});
});
}
So it should get the LocationService
list and the test is as follows:
it('should get locations', function() {
$httpBackend.when('GET', '/api/v1/location/list').respond({status: 'ok', locations: ['loc1', 'loc2']})
$scope.index();
expect($scope.locations.length).toEqual(2);
However, this never happens, because CompanyService
has a promise that never gets resolved in the unit test. How do I either mock the returned promise of CompanyService
or bypass it?
Simply mock the call using createSpyObj
method from Jasmine:
describe('one test', function(){
var deferred, CompanyService, $scope;
beforeEach(inject(function ($q, $rootScope, $controller) {
params = {
$scope: $rootScope.$new(),
CompanyService = jasmine.createSpyObj('CompanyService', ['initialized'])
}
params.CompanyService.initialized.andCallFake(function () {
deferred = $q.defer();
return deferred.promise; //will fake to return a promise, in order to reach it inside the test
});
$controller('YourController', params);
});
it('my test', function(){
deferred.resolve({}); //empty object returned for the sample but you can set what you need to be returned
$scope.$digest(); //important in order to resolve the promise
//at this time, the promise is resolved! so your logic to test can be placed here
});
});
Short answer: Add $scope.$apply();
after calling $scope.$index();
.
Long answer: Your problem is probably due to the way $q propagates promises resolution. Indeed resolution only happens when $digest is performed. I don't know why $digest is not performed during tests whereas it is during regular use, but this solution is suggested anyway in the Angular documentation here: https://docs.angularjs.org/api/ng/service/$q .
What's more you could directly use $scope.$digest();
in your case instead of $scope.$apply();
since $apply is only a wrapper that runs any function passed to it before calling $digest.