web-dev-qa-db-fra.com

Comment tester correctement les promesses unitaires de jQuery en utilisant Jasmine et/ou Sinon?

J'ai une fonction assez simple qui retourne une promesse jQuery .ajax () en tant que 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
    });
}

Pour la plupart, cette nouvelle interface promesses fonctionne comme un rêve, et éliminer les pyramides de rappel lors de l'utilisation de .ajax () de jQuery est génial. Cependant, je ne peux pas pour toute la vie comprendre comment bien tester ces promesses en utilisant Jasmine et/ou Sinon:

  1. Toute la documentation de Sinon suppose que vous utilisez la vieille école Les rappels; Je ne vois pas un seul exemple d'utilisation avec Promises/différées

  2. En essayant d'utiliser un espion Jasmine ou Sinon pour espionner $ .ajax, l'espion Remplace en fait la promesse. Ses clauses done, fail, Et always n'existent plus sur la fonction ajax. jamais résoudre et jette une erreur à la place

J'adorerais vraiment un exemple ou deux de la façon de tester ces nouvelles promesses jQuery .ajax () avec les bibliothèques de test susmentionnées. J'ai parcouru le filet assez intensément et je n'ai rien rajouté pour le faire. La seule ressource que j’ai trouvée mentionnait l’utilisation de Jasmine.ajax, mais j’aimerais éviter cela, si possible, car Sinon fournit la plupart des mêmes fonctionnalités prêtes à l’emploi.

55
J. Ky Marsh

Ce n'est pas si complexe en fait. Il suffit de retourner une promesse et de la résoudre selon 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

105
ggozad

quelque chose dans ce sens/avec sinon et jQuery différé

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
yxa

La solution donnée par @ggozad ne fonctionnera pas si vous utilisez des éléments tels que .complete().

Mais j’ai fait un plugin pour faire exactement ceci: 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');
0
damio

Voici une approche plus simple avec juste 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 rappel sont celles que j'utilise dans mon test pour conduire à une exécution réussie ou erronée.

0
sam