0

I'm trying to mock up a promise in some Angular unit tests.

I can't understand why the then() section below is never firing. Can any one advise?

beforeEach(inject(function ($controller, $rootScope, $q) {
  scope = $rootScope.$new();

  var mockFactory = {
    getData: function() { 
      var deferred = $q.defer();
      deferred.resolve({data: [1,2,3], widget: null});
      return deferred.promise;
    }
  };
  mockFactory.getData()
    .then(function (response) {
      console.log('mockFactory', response);
    });

  }));

I'm not sure if this issue is related.

Community
  • 1
  • 1
Richard
  • 62,943
  • 126
  • 334
  • 542

1 Answers1

3

Angular's promise library $q is integrated with $rootScope. The resolutions to the promise aren't applied until the next round of the Angular digest loop. This is a real gotcha while testing, because you have to force it by calling $rootScope.$apply() after you resolve promises.

Your example is kind of janky, and incomplete. You're also resolving the promise before you return it. I don't know exactly what you are trying to do, and I won't guess. But I think something like the following will get the console.log that you're looking for.

beforeEach(inject(function ($controller, $rootScope, $q) {
    scope = $rootScope.$new();
    var deferred;

    var mockFactory = {
        getData: function() { 
            deferred = $q.defer();
            return deferred.promise;
        }
    };

    mockFactory.getData()
        .then(function (response) {
            console.log('mockFactory', response);
        });

    deferred.resolve({data: [1,2,3], widget: null});
    $rootScope.$apply();
}));

I have made a working example of unit testing angularjs promises.

It is here: plunkr

I wrote an accompanying blog about this topic on projectpoppycock

Cheers! And good luck promise mocking.

nackjicholson
  • 4,557
  • 4
  • 37
  • 35