2012-10-30 3 views
55

Ho una funzione abbastanza semplice che restituisce una .ajax jQuery) promessa (come ad esempio:Come testare correttamente l'unità jQuery's .ajax() promette di usare Jasmine e/o Sinon?

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

Per la maggior parte, questa nuova interfaccia promesse funziona come un sogno, ed eliminando le piramidi di richiamata quando si utilizza jQuery di .ajax() è fantastico. Tuttavia, non posso per la vita di me capire come verificare correttamente queste promesse con Jasmine e/o Sinon:

  1. tutta la documentazione di Sinon presuppone che si sta utilizzando vecchia scuola callback; Non vedo un solo esempio di come usarlo con promesse/deferreds

  2. Quando si tenta di utilizzare un gelsomino o Sinon spiare spiare $ .ajax, la spia è effettivamente sovrascrive la promessa, per cui il suo done, fail, e always clausole non esistono più sulla funzione ajax, quindi la promessa non risolve e lancia un errore invece

mi piacerebbe davvero solo l'amore un esempio o due di come testare questi nuovi jQuery .ajax() promette con le librerie di test sopra menzionate. Ho raschiato la rete abbastanza intensamente e non ho davvero dragato nulla per farlo. L'unica risorsa che ho trovato menzionata usando Jasmine.ajax, ma vorrei evitare che, se possibile, visto che Sinon fornisce la maggior parte delle stesse funzionalità out-of-the-box.

risposta

105

In realtà non è così complesso. È sufficiente restituire una promessa e risolverla in base al tuo caso.

Ad esempio:

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

per un successo, o

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

per un fallimento.

Per Jasmine 2.0 la sintassi è leggermente cambiata:

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

il metodo .andCallFake() non esiste in Jasmine 2.0

+0

Questo ha funzionato meravigliosamente; grazie mille! –

+0

Nessun problema, un piacere;) – ggozad

+8

Qualche idea per il modo Sinon? – lucke84

16

qualcosa in queste righe/con Sinon e jQuery deferreds

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

Hai dimenticato i callback 'success' e' error'. – Vanuan

0

Ecco un approccio più semplice con solo javascript.

Le istruzioni if ​​all'interno di ciascuna richiamata sono quelle che utilizzo nel test per eseguire correttamente o l'esecuzione di errori.

0

La soluzione fornita da @ggozad non funzionerà se si utilizzano elementi come .complete().

Ma, evviva, gelsomino fatto un plugin per fare esattamente questo: 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');