How to correctly use unit test jQuery.ajax () promises Jasmine and / or Sinon?

I have a pretty simple function that returns jQuery.ajax () as such:

CLAW.controls.validateLocation = function(val, $inputEl) { return $.ajax({ url: locationServiceUrl + 'ValidateLocation/', data: { 'locationName': val }, beforeSend: function() { $inputEl.addClass('busy'); } }).done(function(result) { // some success clauses }).fail(function(result) { // some failure clauses }).always(function() { // some always clauses }); } 

For the most part, this new promises interface works like a dream and eliminates callback pyramids when using jQuery.ajax () perfectly. However, I cannot understand for life how to properly test these promises using Jasmine and / or Sinon:

  • All Sinon documentation assumes that you are using an old school callbacks; I do not see any example of how to use it with promises / deferreds

  • When trying to use Jasmine or Sinon spying to spy on $ .ajax, the spy effectively rewrites the promise, so its done , fail , and always no longer exists in the ajax function, so the promise never resolves and throws an error instead

I would really like an example or two of how to check out these new jQuery.ajax () promises with the above test libraries. I was pretty much looking for a "network" and actually did nothing. One resource I found is mentioned using Jasmine.ajax, but I would like to avoid this if possible, because Sinon provides most of the same features out of the box.

+55
jquery unit-testing jasmine sinon
Oct 30 '12 at 22:15
source share
4 answers

This is actually not so difficult. It is enough to return the promise and decide it in accordance with your case.

For example:

 spyOn($, 'ajax').andCallFake(function (req) { var d = $.Deferred(); d.resolve(data_you_expect); return d.promise(); }); 

for success, or

 spyOn($, 'ajax').andCallFake(function (req) { var d = $.Deferred(); d.reject(fail_result); return d.promise(); }); 

for failure.

For Jasmine 2.0, the syntax has changed slightly:

 spyOn($, 'ajax').and.callFake(function (req) {}); 

.andCallFake () method does not exist in Jasmine 2.0

+105
Oct 31 '12 at 19:07
source share

something along these lines / with sinones and jQuery deferred

 ajaxStub = sinon.stub($, "ajax"); function okResponse() { var d = $.Deferred(); d.resolve( { username: "testuser", userid: "userid", success: true } ); return d.promise(); }; function errorResponse() { var d = $.Deferred(); d.reject({},{},"could not complete"); return d.promise(); }; ajaxStub.returns(okResponse()); ajaxStub.returns(errorResponse()); 
+16
Apr 18 '13 at 17:45
source share

Here's a simpler approach using only javascript.

 quoteSnapshots: function (symbol, streamId) { var FakeDeferred = function () { this.error = function (fn) { if (symbol.toLowerCase() === 'bad-symbol') { fn({Error: 'test'}); } return this; }; this.data = function (fn) { if (symbol.toLowerCase() !== 'bad-symbol') { fn({}); } return this; }; }; return new FakeDeferred(); } 

The if statements inside each callback is what I use in my test to succeed or fail.

0
Apr 26 '13 at 12:14
source share

The solution given by @ggozad will not work if you use things like .complete() .

But, cheers, jasmine made a plugin to do just that: http://jasmine.imtqy.com/2.0/ajax.html

 beforeEach(function() { jasmine.Ajax.install(); }); afterEach(function() { jasmine.Ajax.uninstall(); }); //in your tests expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url'); 
0
Jan 21 '16 at 1:57
source share



All Articles