114 votes

Comment vérifier les événements AJAX de jQuery avec Jasmine ?

J'essaie d'utiliser Jasmine pour écrire des spécifications BDD pour des requêtes AJAX jQuery de base. J'utilise actuellement Jasmine en mode autonome (c'est-à-dire via SpecRunner.html). J'ai configuré SpecRunner pour charger jquery et d'autres fichiers .js. Une idée de la raison pour laquelle ce qui suit ne fonctionne pas ? has_returned ne devient pas vrai, même si l'alerte "yuppi !" s'affiche bien.

describe("A jQuery ajax request should be able to fetch...", function() {

  it("an XML file from the filesystem", function() {
    $.ajax_get_xml_request = { has_returned : false };  
    // initiating the AJAX request
    $.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
             success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } }); 
    // waiting for has_returned to become true (timeout: 3s)
    waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
    // TODO: other tests might check size of XML file, whether it is valid XML
    expect($.ajax_get_xml_request.has_returned).toEqual(true);
  }); 

});

Comment puis-je tester que le callback a été appelé ? Toute référence à des blogs ou à des documents relatifs au test de jQuery asynchrone avec Jasmine sera grandement appréciée.

merci d'avance

233voto

Alex York Points 2668

Je suppose qu'il y a deux types de tests que vous pouvez faire :

  1. Des tests unitaires qui simulent la requête AJAX (en utilisant les espions de Jasmine), ce qui vous permet de tester tout le code qui s'exécute. juste avant la requête AJAX, et juste après . Vous pouvez même utiliser Jasmine pour simuler une réponse du serveur. Ces tests seraient plus rapides - et ils n'auraient pas besoin de gérer un comportement asynchrone - puisqu'il n'y a pas de véritable AJAX en cours.
  2. Des tests d'intégration qui effectuent de véritables requêtes AJAX. Ces tests doivent être asynchrones.

Jasmine peut vous aider à réaliser ces deux types de tests.

Voici un exemple de la façon dont vous pouvez simuler la requête AJAX, puis écrire un test unitaire pour vérifier que la requête AJAX simulée est dirigée vers la bonne URL :

it("should make an AJAX request to the correct URL", function() {
    spyOn($, "ajax");
    getProduct(123);
    expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});

function getProduct(id) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    });
}

Voici un test unitaire similaire qui vérifie que votre callback a été exécuté, lorsqu'une requête AJAX s'est terminée avec succès :

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    });
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    expect(callback).toHaveBeenCalled();
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: callback
    });
}

Enfin, vous avez laissé entendre ailleurs que vous pourriez vouloir écrire des tests d'intégration qui font de véritables requêtes AJAX - à des fins d'intégration. Cela peut être fait en utilisant les fonctionnalités asynchrones de Jasmine : waits(), waitsFor() et runs() :

it("should make a real AJAX request", function () {
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    waitsFor(function() {
        return callback.callCount > 0;
    });
    runs(function() {
        expect(callback).toHaveBeenCalled();
    });
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "data.json",
        contentType: "application/json; charset=utf-8"
        dataType: "json",
        success: callback
    });
}

13voto

user533109 Points 101

Regardez le projet jasmine-ajax : http://github.com/pivotal/jasmine-ajax .

Il s'agit d'une aide immédiate qui (pour jQuery ou Prototype.js) se substitue à la couche XHR afin que les requêtes ne soient jamais envoyées. Vous pouvez alors attendre tout ce que vous voulez de la requête.

Il vous permet ensuite de fournir des réponses fixes pour tous vos cas, puis d'écrire des tests pour chaque réponse que vous souhaitez : succès, échec, non autorisé, etc.

Il sort les appels Ajax du domaine des tests asynchrones et vous offre une grande flexibilité pour tester le fonctionnement de vos gestionnaires de réponses.

7voto

skipy Points 684

Voici un exemple simple de suite de tests pour une application js comme celle-ci

var app = {
               fire: function(url, sfn, efn) {
                   $.ajax({
                       url:url,
                       success:sfn,
                       error:efn
                   });
                }
         };

un exemple de suite de test, qui appellera le callback basé sur le regexp url

describe("ajax calls returns", function() {
 var successFn, errorFn;
 beforeEach(function () {
    successFn = jasmine.createSpy("successFn");
    errorFn = jasmine.createSpy("errorFn");
    jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
      function (options) {
          if(/.*success.*/.test(options.url)) {
              options.success();
          } else {
              options.error();
          }
      }
    );
 });

 it("success", function () {
     app.fire("success/url", successFn, errorFn);
     expect(successFn).toHaveBeenCalled();
 });

 it("error response", function () {
     app.fire("error/url", successFn, errorFn);
     expect(errorFn).toHaveBeenCalled();
 });
});

5voto

Justin Searls Points 3078

Lorsque je spécifie du code ajax avec Jasmine, je résous le problème en espionnant la fonction dépendante qui initie l'appel distant (comme, par exemple, $.get ou $ajax). Ensuite, je récupère les callbacks définis sur cette fonction et je les teste discrètement.

Voici un exemple que j'ai reçu récemment :

https://gist.github.com/946704

3voto

Lars Points 421

J'ai un article assez approfondi sur la façon de tester les fonctions javascript asynchrones en utilisant Jasmine. Si cela peut vous aider, voici l'article : http://www.larsavery.com/blog/how-to-test-asynchronous-javascript-functions-using-jasmine/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X