¿Cómo realizar una prueba adecuada de la unidad. Las promesas .ajax () de jQuery usan Jasmine y / o Sinon?

Tengo una función bastante sencilla que devuelve una promesa jQuery .ajax () como tal:

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 }); } 

En su mayor parte, esta nueva interfaz de promesas funciona como un sueño, y eliminar las pirámides de callback cuando se usa .ajax () de jQuery es genial. Sin embargo, no puedo, por mi vida, descubrir cómo probar adecuadamente estas promesas usando Jasmine y / o Sinon:

  1. Toda la documentación de Sinon supone que estás usando devoluciones de llamada de la vieja escuela; No veo un solo ejemplo de cómo usarlo con promesas / aplazados

  2. Cuando se intenta usar un espía Jasmine o Sinon para espiar $ .ajax, el espía está sobrescribiendo efectivamente la promesa, por lo que su done , fail y always ya no existen cláusulas en la función ajax, por lo que la promesa nunca se resuelve y arroja un error en lugar

Realmente me encantaría un ejemplo o dos de cómo probar estas nuevas promesas jQuery .ajax () con las librerías de pruebas mencionadas anteriormente. He rastreado la red con bastante intensidad y realmente no he desenterrado nada al hacerlo. El único recurso que encontré se menciona utilizando Jasmine.ajax, pero me gustaría evitarlo si es posible, ya que Sinon proporciona la mayoría de las mismas capacidades de forma inmediata.

No es tan complejo en realidad. Basta con devolver una promesa y resolverla de acuerdo con su caso.

Por ejemplo:

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

para un éxito, o

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

por un fracaso

Para Jasmine 2.0 la syntax ha cambiado ligeramente:

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

El método .andCallFake () no existe en Jasmine 2.0

algo en este sentido / con sinon y jQuery aplazados

 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()); 

Aquí hay un enfoque más simple con solo 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(); } 

Las declaraciones if dentro de cada callback son lo que uso en mi prueba para impulsar una ejecución exitosa o errónea.

La solución dada por @ggozad no funcionará si usas cosas como .complete() .

Pero, hurra, el jasmine hizo un complemento para hacer exactamente esto: http://jasmine.github.io/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');