How to resolve promises in AngularJS, Jasmine 2.0 when there is no $scope to force a digest?

Terry picture Terry · Jun 3, 2014 · Viewed 26.7k times · Source

It seems that promises do not resolve in Angular/Jasmine tests unless you force a $scope.$digest(). This is silly IMO but fine, I have that working where applicable (controllers).

The situation I'm in now is I have a service which could care less about any scopes in the application, all it does it return some data from the server but the promise doesn't seem to be resolving.

app.service('myService', function($q) {
  return {
    getSomething: function() {
      var deferred = $q.defer();
      deferred.resolve('test');
      return deferred.promise;
    }
  }
});

describe('Method: getSomething', function() {
  // In this case the expect()s are never executed
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
    });

    done();
  });

  // This throws an error because done() is never called.
  // Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
      done();
    });
  });
});

What is the correct way to test this functionality?

Edit: Solution for reference. Apparently you are forced to inject and digest the $rootScope even if the service is not using it.

  it('should get something', function($rootScope, done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
    });

    $rootScope.$digest();
    done();
  }); 

Answer

pkozlowski.opensource picture pkozlowski.opensource · Jun 3, 2014

You need to inject $rootScope in your test and trigger $digest on it.