Currently, I am in the process of writing some unit tests for my controller that utilizes promises. The code snippet in question is as follows:
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.$apply(function () {
$scope.contacts = data;
});
});
In order to properly test this functionality, I have created a mock for my UserService and here is my unit test:
beforeEach(inject(function ($rootScope, $controller, $q, $routeParams) {
$routeParams.contactId = contactId;
window.localStorage.clear();
UserService = {
getUser: function () {
def = $q.defer();
return def.promise;
}
};
spyOn(UserService, 'getUser').andCallThrough();
scope = $rootScope.$new();
ctrl = $controller('ContactDetailController', {
$scope: scope,
UserService:UserService
});
}));
it('expects to receive 1 contact', function () {
expect(scope.contacts).not.toBeDefined();
def.resolve(contact);
scope.$apply();
expect(scope.contacts.surname).toEqual('NAME');
expect(scope.contacts.email).toEqual('EMAIL');
});
However, when running this test, it results in the following error message:
Error: [$rootScope:inprog] $digest already in progress
When removing the $scope.$apply from the controller, the test passes, but the controller's functionality is compromised:
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.contacts = data;
});
So, I am currently seeking advice on how to handle this situation moving forward. Any suggestions would be greatly appreciated.
Based on replies received, it has been pointed out that the $apply is not occurring in the UserService, but rather within the controller itself. Here is an updated snippet showcasing where the $apply is being utilized:
EDIT: The $apply block is implemented in the controller in this manner:
appController.controller('ContactDetailController', function ($scope, $routeParams, UserService) {
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.$apply(function () {
$scope.contacts = data;
});
});
Here is the implementation of the actual UserService:
function getUser(user) {
if (user === undefined) {
user = getUserId();
}
var deferred = Q.defer();
$http({
method: 'GET',
url: BASE_URL + '/users/' + user
}).success(function (user) {
deferred.resolve(user);
});
return deferred.promise;
}