55 votes

Comment tester correctement les promesses .ajax() de jQuery à l'aide de Jasmine et/ou Sinon ?

J'ai une fonction assez simple qui renvoie une promesse jQuery .ajax() comme telle :

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

Dans l'ensemble, cette nouvelle interface de promesses fonctionne comme un rêve, et l'élimination des pyramides de callback lors de l'utilisation de .ajax() de jQuery est formidable. Cependant, je n'arrive pas à trouver comment tester correctement ces promesses à l'aide de Jasmine et/ou Sinon :

  1. Toute la documentation de Sinon suppose que vous utilisez la vieille méthode à l'ancienne ; je ne vois pas un seul exemple de comment l'utiliser avec des promesses/deferreds

  2. Lorsque l'on tente d'utiliser un espion Jasmine ou Sinon pour espionner $.ajax, l'espion écrase effectivement le prometteur. écrase effectivement la promesse, de sorte que sa fonction done , fail , et always n'existent plus sur la fonction ajax, de sorte que la promesse n'est jamais résolue et génère une erreur à la place.

J'aimerais vraiment avoir un ou deux exemples de la façon de tester ces nouvelles promesses jQuery .ajax() avec les librairies de test susmentionnées. J'ai parcouru le net assez intensément et je n'ai pas vraiment trouvé quelque chose pour le faire. La seule ressource que j'ai trouvée mentionnait l'utilisation de Jasmine.ajax, mais j'aimerais éviter cela si possible, vu que Sinon fournit la plupart des mêmes capacités prêtes à l'emploi.

106voto

ggozad Points 8910

Ce n'est pas si complexe en fait. Il suffit de retourner une promesse et de la résoudre en fonction de votre cas.

Par exemple :

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

pour un succès, ou

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

pour un échec.

Pour Jasmine 2.0, la syntaxe a légèrement changé :

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

la méthode .andCallFake() n'existe pas dans Jasmine 2.0

16voto

yxa Points 51

Quelque chose de ce genre / avec sinon et les différés de jQuery

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

0voto

sam Points 379

Voici une approche plus simple avec juste du 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();
            }

Les instructions if à l'intérieur de chaque callback sont celles que j'utilise dans mon test pour déclencher l'exécution d'un succès ou d'une erreur.

0voto

damio Points 3042

La solution donnée par @ggozad ne fonctionnera pas si vous utilisez des choses comme .complete() .

Mais, hourra, Jasmine a créé un plugin pour faire exactement cela : 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');

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