web-dev-qa-db-fra.com

Stubbing window.location.href avec Sinon

J'essaie de tester du code côté client et pour cela, je dois bloquer la valeur de window.location.href propriété utilisant Mocha/Sinon.

Ce que j'ai essayé jusqu'à présent ( en utilisant cet exemple ):

describe('Logger', () => {
    it('should compose a Log', () => {
        var stub = sinon.stub(window.location, 'href', 'http://www.foo.com');
    });
});

Le coureur affiche l'erreur suivante:

TypeError: le stub personnalisé doit être une fonction ou un descripteur de propriété

Changer le code de test en:

describe('Logger', () => {
    it('should compose a Log', () => {
        var stub = sinon.stub(window.location, 'href', {
            value: 'foo'
        });
    });
});

Ce qui donne cette erreur:

TypeError: tentative d'envelopper la propriété de chaîne href comme fonction

Passer une fonction comme troisième argument à sinon.stub ne fonctionne pas non plus.

Existe-t-il un moyen de fournir un faux window.location.href chaîne, évitant également la redirection (puisque je teste dans le navigateur)?

22
Francesco Pezzella

Les talons ne peuvent pas remplacer les attributs, seulement les fonctions.

L'erreur levée renforce ceci:

TypeError: le stub personnalisé doit être une fonction ou un descripteur de propriété

De la documentation:

Quand utiliser des talons?

Utilisez un talon lorsque vous souhaitez:

  1. Contrôlez le comportement d'une méthode à partir d'un test pour forcer le code vers un chemin spécifique. Par exemple, forcer une méthode à lancer une erreur afin de tester la gestion des erreurs.

  2. Lorsque vous souhaitez empêcher une méthode spécifique d'être appelée directement (peut-être parce qu'elle déclenche un comportement indésirable, tel qu'un XMLHttpRequest ou similaire).

http://sinonjs.org/releases/v2.0.0/stubs/


Solution possible

Alors que de nombreux objets intégrés peuvent être remplacés (pour les tests), certains ne le peuvent pas. Pour ces attributs, vous pouvez créer des objets de façade que vous devez ensuite utiliser dans votre code et pouvoir les remplacer dans les tests.

Par exemple:

var loc = {

    setLocationHref: function(newHref) {
        window.location.href = newHref;
    },

    getLocationHref: function() {
        return window.location.href;
    }

};

Usage:

loc.setLocationHref('http://acme.com');

Vous pouvez ensuite dans votre test écrire

var stub = sinon.stub(loc, 'setLocationHref').returns('http://www.foo.com');

Notez l'appel chaîné returns(). Il y avait une autre erreur dans votre code: le troisième argument doit être une fonction, pas une valeur sur un autre type. C'est un rappel, pas ce que l'attribut doit retourner.

Voir le code source de stub()

8
try-catch-finally

Vous devez utiliser global pour simuler l'objet window pour votre test dans beforeEach ou it

par exemple.

it('should compose a Log', () => {
   global.window = {
       location: {
           href: {
               value: 'foo'
           }
       }
   }
  //.... call the funciton 
});
17
KhaledMohamedP

Utilisez window.location.assign(url) au lieu de remplacer la valeur de window.location. Ensuite, vous pouvez simplement stub la méthode assign sur le window.location objet.

http://www.w3schools.com/jsref/met_loc_assign.asp


MISE À JOUR: J'ai testé cela dans un navigateur sans tête, mais cela peut ne pas fonctionner si vous exécutez vos tests dans Chrome. Voir réponse de @ try-catch-finally .

13
Danny Andrews