I've been trying to wrap my head around Jasmine 2.0 and AngularJS promises. I know that:
- Jasmine 2.0 introduced the
done
function to replace the oldruns
andwaitsFor
functions - AngularJS
$q
promises will not resolve until a digest cycle is triggered
How can I test AngularJS promises using the new async syntax in Jasmine 2.0?
After your call to
promise.resolve()
:$timeout.flush()
. This will force a digest cycle and propagate the promise resolutiondone()
. This tells Jasmine the async tests have completedHere's an example (Demo on Plunker):
This answer won't add anything new to those of above, it is only intended to articulate the answer in more detailed way, as it worked for me. When I occurred the issue described in a question above, I spent much time tryng to find a way to make sure all promises had their time to finish and all assertions were asserted.
In my case I had a chain of promises, and after each of them I need to ensure the results do match my expectation. I did not create any promise using
deferred
, I rather invoked the existing ones.So, the thing is that
$timeout.flush()
was completely enough for me. My working test looks like this:This test is dedicated to make sure that commandHistory object works fine, it has to actions:
execute
andunExecute
, and three methods:execute
,undo
,redo
, all of which return promises.Without
$timeout.flush()
, all I had in log output wasAll together
, and no further log messages. Adding$timeout.flush()
has fixed everything up, and now I have all messages shown and all assertions executedUPDATE There's another option: you can write your test suite without chaining promises with
then
, but simply flushing after each promise has been called, so that to make sure it completes:Please pay attention to the fact in some cases, when my methods like
undo
andredo
do not return promise, I call$timeout.verifyNoPendingTasks()
instead offlush
. Which is hard to say if it's good or bad.Yet in this case test looks more reasonable and much simpler.
For me the
$timeout.flush()
didn't work very well, but I've multiple async calls in my spec. I found the$rootScope.$apply()
, as a method to force thedigest
on each async call.It is like a chained async calls thing. Hope it helps the conversation. Regards