0

Is it possible to resolve an angular promise immediately and effectively have the code behave like a synchronous call? I know this defeats the purpose of promises, but I want to do this for unit testing purposes. My testing shows that the then is called right away, but I am not sure if there is a potential timing issue here where the then is still considered asynch?

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

someService().then(function(obj){
  //will this be executed right away just like it would if this was a synchronous call?

  // more code here under test
});

var myVal = 10;

Will the myVal assignment be executed before the then callback? Or can I trust that the then will always go right away?

user4131376
  • 65
  • 10
  • In my opinion this breaks the concept of correct unit testing by modifying code execution paths between unit tests and actual application execution. However... Without overriding the angular-promise implementation for `then` -> No, this will always behave asynchronously. – SnareChops Oct 11 '14 at 03:22
  • The point is to mock the service and focus on testing the then without worrying about a dependency to the service. I would normally separate the logic out to a separate testable entity, but don't have the luxury of changing code here. – user4131376 Oct 11 '14 at 03:27
  • documentation says **regardless of when the promise was or will be resolved** that mean if the result is already available then also "then" is supposed to be invoked immediately without any timing or async issue. – gp. Oct 11 '14 at 03:27
  • try `scope.$digest()` – Khanh TO Oct 11 '14 at 03:56
  • possible duplicate of [Unit-test promise-based code in Angular](http://stackoverflow.com/questions/16081586/unit-test-promise-based-code-in-angular) – dnozay Oct 11 '14 at 03:59
  • This is exactly how I have my test structured, but it seems this may have a potential timing bug where the test might be done before the then executes. I don't see a safeguard that ensures that all then clauses are done. – user4131376 Oct 11 '14 at 04:03

1 Answers1

0

Your unit tests can mock the service and return a promise; that way your .then() can be tested.

This topic is covered in similar questions:

The gist is:

  • call beforeEach and inject to mock your servcice,
  • your mock service to return a promise

Back to your question:

Will the myVal assignment be executed before the then callback? Or can I trust that the then will always go right away?

Someone (@gp) covered that in the comments. The callback is async, so it may or may not be executed right away. To ensure your assignment is done in the proper order, you can initialize it beforehand, or in a then callback and chain those properly.

Community
  • 1
  • 1
dnozay
  • 23,846
  • 6
  • 82
  • 104
  • Yes, that is what this does, but the then is still called asynchronously, so it seems the test still needs to handle that aspect in addition to what I actually want to test. – user4131376 Oct 11 '14 at 03:59
  • the question is **why** you need it to be synchronous? plus if the promise is already resolve, `then()` gets called right away. – dnozay Oct 11 '14 at 04:01
  • This is exactly how I have my test structured, but it seems this may have a potential timing bug where the test might be done before the then executes. I don't see a safeguard that ensures that all then clauses are done. – user4131376 Oct 11 '14 at 04:03
  • can you please give more details about the timing bug? – dnozay Oct 11 '14 at 04:05
  • Apparently the then is not executed next even if the promise is resolved. It is still async. – user4131376 Oct 11 '14 at 04:05
  • well "right away" is dictated by the code that comes after it. It will have to wait until the next code slice is done – user4131376 Oct 11 '14 at 04:09