title: Testing callback from service in an AngularJS controller spec
body: <p>I've got a Controller that uses a service that has a callback function on success.</p>
  
  <p>Controller Function</p>
  
  <pre><code>itemCtrl.save = function () {
      ItemService.save({ username: SessionService.getUsername() }, itemCtrl.item, function (res) {
          $scope.$emit('UPDATE_ITEMS');
          $modalInstance.close(res);
      });
  };
  </code></pre>
  
  <p>spec</p>
  
  <pre><code>it('should close the modal on successful save', function () {
      spyOn(itemSrv, 'save').and.callFake(function () {
          deferred = q.defer();
          deferred.resolve();
          return deferred.promise;
      });
      spyOn(modalInst, 'close').and.callThrough();
      ItemCtrl.save();
      scope.$digest();
      expect(modalInst.close).toHaveBeenCalled();
  });
  </code></pre>
  
  <p>When I run this test in karma is failing because the close function of the modalinstance is not called. I think the problem is on the spec description, because the functionality is working in the app.
  I have a few questions about this:</p>
  
  <ul>
  <li>Is this the best way of describing callbacks on service calls in a controller?</li>
  <li>How should I describe my specs using callbacks?</li>
  </ul>
  
  <p>-- EDIT --</p>
  
  <p>I've changed my service calls to make them handle results as promises:</p>
  
  <pre><code>itemCtrl.save = function () {
      ItemService.save({ username: SessionService.getUsername() }, horas.trabajo).$promise.then(function (res) {
          $scope.$emit('UPDATE_ITEMS');
          $modalInstance.close(res);
      });
  };
  </code></pre>
  
  <p>I guess I'm not passing the tests because my service does not return a promise (it has a promise attribute which I'm calling to emit the event and close the modalInstance). But still I'm getting confused about how to return a promise using ng-resource. </p>
  
  <p>My attempt to solve it was returning an object with a $promise attribute, which contains the promise that q provides.</p>
  
  <p>spec</p>
  
  <pre><code>it('should close the modal on successful save', function () {
      spyOn(itemSrv, 'save').and.callFake(function () {
          deferred = q.defer();
          deferred.resolve();
          return {$promise: deferred.promise};
      });
      spyOn(modalInst, 'close').and.callThrough();
      ItemCtrl.save();
      scope.$digest();
      expect(modalInst.close).toHaveBeenCalled();
  });
  </code></pre>