How to mock JQuery with Jasmine?
How can I test that a certain JQuery selector has been executed with Jasmine? I'm trying to do the following:
spyOn($.fn, 'init').andCallThrough();
// my code
expect($.init).toHaveBeenC开发者_Python百科alled();
But after this call, $('div')
returns Object { selector="div", context=document, NaN=div.spec, more...}
, though it has to return (and $.fn.init('div')
does return it): [div.jasmine_reporter, div.banner, div.logo, 4 more...]
. This stuff naturally breaks the code since the JQuery object is no longer usable.
Example:
Say I want to test that a JQuery selector has been called, I write:
it('tests', function() {
spyOn($.fn, 'init').andCallThrough();
$('html');
expect($.init).toHaveBeenCalled();
});
This result it an error from Jasmine: Error: Expected a spy, but got undefined.
. Then I set a breakpoint in FireBug on $('html') line and when I get there and try to watch, what the value of $('html')
is, I get:
Object { selector="html", context=document, NaN=html, more...}
If I comment out spyOn
, on that line $('html')
evaluates to:
[html]
Which is what I expected to see with spyOn
as well.
Well it looks like Jasmine does it's spy stuff by replacing the spied-on object with a wrapped version, and that seems to be messing up jQuery as a whole because (from the jQuery source code):
// The jQuery object is actually just the init constructor 'enhanced'
I'd suggest trying to spy on one of the functions that init uses, specifically "merge". If you look at the jQuery code, you'll see that any HTML=>DOM stuff ultimately gets returned through a merge call:
return jQuery.merge( this, selector );
(that's line 152 if you happen to be looking at the source of jQuery 1.5.1).
By spying on merge you should be able to test whatever you're testing, without inadvertently replacing the guts of jQuery.
精彩评论