user4131376
user4131376

Reputation: 65

Jasmine async test using promises

I am doing some Jasmine testing using angular promises and have a question related to timing. Found an answer here Unit-test promise-based code in Angular, but need clarification about how this works. Given that the then method is always handled in an asynchronous way how is the following test guaranteed to pass. Isn't there are risk that the expect will run ahead of the then block being executed and run the expect before the value has been assigned. Or... does the digest cycle guarantee that the value will be assigned before the expect runs. Meaning, a digest cycle will effectively behave like a blocking call that guarantees that the promises are all resolved before the code is allowed to proceed.

function someService(){
  var deferred = $q.defer();
  deferred.resolve(myObj); 
  return deferred.promise;
} 

it ('testing promise', function() {
  var res;
  var res2;
  someService().then(function(obj){
    res = "test";
  });

  someService().then(function(obj){
    res2 = "test2";
  });

  $rootScope.$apply(); 
  expect(res).toBe('test');
  expect(res2).toBe('test2');
});

Upvotes: 0

Views: 1190

Answers (2)

GarlicFries
GarlicFries

Reputation: 8323

While Michal's answer points to the right idea, the key here is that $apply() is called on the pertinent scope. Here's the example from the Angular docs:

it('should simulate promise', inject(function($q, $rootScope) {
  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { resolvedValue = value; });
  expect(resolvedValue).toBeUndefined();

  // Simulate resolving of promise
  deferred.resolve(123);
  // Note that the 'then' function does not get called synchronously.
  // This is because we want the promise API to always be async, whether or not
  // it got called synchronously or asynchronously.
  expect(resolvedValue).toBeUndefined();

  // Propagate promise resolution to 'then' functions using $apply().
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
}));

Upvotes: 0

Michal Charemza
Michal Charemza

Reputation: 26982

a digest cycle will effectively behave like a blocking call that guarantees that the promises are all resolved before the code is allowed to proceed.

Yes, although more accurately it would guarantee that the success callbacks of resolved promises would have run.

There is a very similar example that shows how the digest cycle is tied to the success callbacks of promises in the docs for $q

Upvotes: 1

Related Questions