Spies: How to expect a method to have been called with a callback?

4,141 views
Skip to first unread message

Jules

unread,
Aug 14, 2011, 8:56:24 PM8/14/11
to Jasmine
When writing OO javascript, you want to use Jasmine to test the
interactions between objects.

Imagine we have we have two classes: resultRenderer and dbQuery.
resultRenderer will ask dbQuery to perform a database query, and
asyncronously receive the results.
So dbQuery needs to call back to resultRenderer once it has the
results.

Take a look at this code:
https://gist.github.com/1145534

Specifically the last line ('What goes here'):
expect(dbQuery.runQueryAsync).toHaveBeenCalledWith(/* What goes here?
*/);

How can you match an argument that is a Function, bound to a specific
object context?

Davis Frank

unread,
Aug 14, 2011, 11:33:53 PM8/14/11
to jasmi...@googlegroups.com
In this case, it's likely better to verify the results of the callback, not just that it was called.

I'd use jasmine.any(Function) to match the callback in the parameters list - function equality is problematic.

--dwf


--
You received this message because you are subscribed to the Google Groups "Jasmine" group.
To post to this group, send email to jasmi...@googlegroups.com.
To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jasmine-js?hl=en.


Jules

unread,
Aug 17, 2011, 8:28:21 PM8/17/11
to Jasmine
> In this case, it's likely better to verify the results of the callback, not
> just that it was called.

I'm trying to test that the resultRenderer correctly uses the dbQuery
object (an interaction between objects).
i.e. "did resultRenderer call dbQuery.runQueryAsync with the correct
callback specified.

Often the callback specified in a TDD environment will just be a mock
- so you can't test the results of the callback.

> I'd use jasmine.any(Function) to match the callback in the parameters list -
> function equality is problematic.

Hmm... unfortunately this doesn't do much to test that the _correct_
callback was specified.

Gregg Van Hove

unread,
Aug 17, 2011, 8:34:04 PM8/17/11
to jasmi...@googlegroups.com
What I've done in the past is check that a function was passed in correctly, as Davis said, with jasmine.any(Function). Then actually invoke the function that was passed in. In your case something like this:

expect(dbQuery.runQueryAsync).toHaveBeenCalledWith(jasmine.any(Function));
dbQuery.runQueryAsync.mostRecentCall.args[0](/* fake results here */);
/* expect various things about the callback's behavior */

-Gregg




--

Rajan Agaskar

unread,
Aug 19, 2011, 9:15:59 AM8/19/11
to jasmi...@googlegroups.com
My preference is to avoid enumerating arguments as much as you can; in this case I would fake the behavior of the dbQuery, and then test either that my callback is called or that my callback is called with suitable fake data and does what I would expect. See here: https://gist.github.com/1156753

andCallFake is a great option for a lot of things where you don't care about the state between the async process triggering and the occurrence of the callback.

Thanks for using Jasmine!

Rajan


--
Reply all
Reply to author
Forward
0 new messages