Testing deferred objects in Angular
October 29, 2014
Consider the two code blocks below. They’re unit testing an asynchronous function
service.getThing, that returns an initial promise, to be resolved at a later time.
So, try and spot the difference between the blocks. It’s a subtle detail that no one else eluded to on the web, that I could find at least. A careful read of Angular’s $q docs finally did it for me. (For the impatient, the correct solution is B).
thing = service.getThing() # returns deferred.promise deferred.resolve someResponse # manual resolve, behind the scenes of `getThing` $rootScope.$apply() expect thing .toEqual expectedThing
thing = null service.getThing() # returns deferred.promise .then (response) -> thing = response deferred.resolve someResponse # manual resolve, behind the scenes of `getThing` $rootScope.$apply() expect thing .toEqual expectedThing
A is what I started with. I’m manually resolving the async request behind
service.getThing. At this point,
thing is a promise, and when I call
thing should be updated to the resolve value
That didn’t work. At that point,
thing is still a promise. At that point, I was cursing the rootScope apply gods.
So, check out B. I’m initializing the response value
thing, and updating it in a callback to
service.getThing. What I’m not doing is reusing the promise. And this works. Do the rootScope apply, and
thing is now your resolve value
It’s subtle and a little bit of magic, but we made it. Good job, you.
Hey, I'm Ian. I build websites and write about what I learn as I go. Follow me on Twitter.