i'm having a javascript function using jquery:
my.namespace.loadSomeStuff = function() {
$.get('/Services/loadStuff', function(c){
$("#stuffDiv").html(c);
});
};
and am trying to write unit tests for this.
now, since this function is not really returning anything and loading some stuff asynchronous using jquery's 'get' i'm having a hard time testing this.
essentially what i would like to do is call this function, wait until it returns something and then access the loaded elements to verify... something like:
my.namespace.loadSomeStuff(function(){
alert('boo');
assertSame('Login', $("#stuffDiv").find(......);
});
now, i created a in the template that calls the unit test, and it will load and display correctly, but the alert or the assert are never executed.
is there a way i can do this without adding a ton 开发者_运维知识库of extra code to every single function i have?
thanks t
You'd have to add an argument to the loadSomeStuff
method to receive the callback function you called in your example code, and then deliberately call it:
my.namespace.loadSomeStuff= function(callback) {
$.get('/Services/loadStuff', function(c){
$("#stuffDiv").html(c);
if (callback!==undefined)
callback();
});
};
I'm not sure it's worth making your code more complicated merely to support unit tests, though you could argue that adding callbacks to async functions is of general-purpose usefulness.
An alternative would be making the test use a crude timeout.
You could use ajaxSuccess
as mentioned by Nick (maybe combined with a timeout, and/or also catching ajaxError
?). But it strikes me this might be adding a bit too much implementation knowledge for a unit test. What if loadSomeStuff
is changed in future to work without an XMLHttpRequest, or maybe only use it sometimes, when it's not cached? Then the unit test will break. Sure, you can update the test to match the implementation, but then that's not really a useful unit test, is it?
You can use the global AJAX events for this, for example:
$(document).ajaxSuccess(function() {
assertSame('Login', $("#stuffDiv").find(......));
});
ajaxSuccess
would happen after each AJAX request, if you wanted an event that ran after all simultaneous requests finished, then ajaxStop
is what you're after. Both of these handlers don't have to be attached to your AJAX methods directly, they can be done in the unit tests.
These are normal events (full list here), so you can .bind()
/.unbind()
as needed, for example when the unit test above is done:
$(document).ajaxSuccess(function() {
assertSame('Login', $("#stuffDiv").find(......));
$(this).unbind('ajaxSuccess'); //cleanup
});
精彩评论