126 votes

Comment se moquer des dépendances pour les tests unitaires dans RequireJS?

J'ai un AMD module que je veux tester, mais je veux, à se moquer de ses dépendances au lieu de charger le réel dépendances. Je suis à l'aide de requirejs, et le code de mon module ressemble à quelque chose comme ceci:

define(['hurp', 'durp'], function(Hurp, Durp) {
  return {
    foo: function () {
      console.log(Hurp.beans)
    },
    bar: function () {
      console.log(Durp.beans)
    }
  }
}

Comment puis-je maquette out hurp et durp donc je peux unité de test?

64voto

Andreas Köberle Points 16453

Donc, après la lecture de ce post, je suis venu avec une solution qui utilisent le requirejs fonction config de créer un nouveau contexte pour ton test où vous pouvez tout simplement se moquer de vos dépendances:

var cnt = 0;
function createContext(stubs) {
  cnt++;
  var map = {};

  var i18n = stubs.i18n;
  stubs.i18n = {
    load: sinon.spy(function(name, req, onLoad) {
      onLoad(i18n);
    })
  };

  _.each(stubs, function(value, key) {
    var stubName = 'stub' + key + cnt;

    map[key] = stubName;

    define(stubName, function() {
      return value;
    });
  });

  return require.config({
    context: "context_" + cnt,
    map: {
      "*": map
    },
    baseUrl: 'js/cfe/app/'
  });
}

De sorte qu'il crée un contexte nouveau où les définitions Hurp et Durp sera fixé par les objets que vous avez transmis à la fonction. Les Mathématiques.aléatoire pour le nom est peut-être un peu sale, mais il fonctionne. Parce que si vous allez avoir un tas de test, vous devez créer un nouveau contexte pour chaque suite pour empêcher la réutilisation de votre se moque, ou de charger des objets fantaisie quand vous voulez la vraie module requirejs.

Dans votre cas, il devrait ressembler à ceci:

(function () {

  var stubs =  {
    hurp: 'hurp',
    durp: 'durp'
  };
  var context = createContext(stubs);

  context(['yourModuleName'], function (yourModule) {

    //your normal jasmine test starts here

    describe("yourModuleName", function () {
      it('should log', function(){
         spyOn(console, 'log');
         yourModule.foo();

         expect(console.log).toHasBeenCalledWith('hurp');
      })
    });
  });
})();

Je suis donc en utilisant cette approche de la production pendant un certain temps et il est vraiment robuste.

44voto

busticated Points 917

vous voudrez peut-être consulter la nouvelle Squire.js lib

à partir de la documentation:

Squire.js est une dépendance de l'injecteur pour Require.js les utilisateurs de faire se moquant de dépendances facile!

17voto

Jergason Points 7748

J'ai trouvé trois solutions différentes à ce problème, aucun d'entre eux agréable.

La Définition Des Dépendances Inline

define('hurp', [], function () {
  return {
    beans: 'Beans'
  };
});

define('durp', [], function () {
  return {
    beans: 'durp beans'
  };
});

require('hurpdhurp', function () {
  // test hurpdurp in here
});

Fugly. Vous avez d'encombrer vos tests avec beaucoup de AMD passe-partout.

Le Chargement Se Moquer De Dépendances À Partir Des Chemins Différents

Cela implique l'utilisation d'une autre config.js fichier pour définir les chemins d'accès de tous les liens qui pointent vers se moque de la place de l'original dépendances. C'est aussi moche, nécessitant la création de tonnes de test de fichiers et les fichiers de configurations.

Faux Nœud

C'est ma solution actuelle, mais il est encore un des plus terribles.

Vous créez votre propre define fonction de votre propre se moque du module et de mettre vos tests dans le rappel. Ensuite, vous eval le module d'exécution de vos tests, comme suit:

var fs = require('fs')
  , hurp = {
      beans: 'BEANS'
    }
  , durp = {
      beans: 'durp beans'
    }
  , hurpDurp = fs.readFileSync('path/to/hurpDurp', 'utf8');
  ;



function define(deps, cb) {
  var TestableHurpDurp = cb(hurp, durp);
  // now run tests below on TestableHurpDurp, which is using your
  // passed-in mocks as dependencies.
}

// evaluate the AMD module, running your mocked define function and your tests.
eval(hurpDurp);

C'est ma solution préférée. Il semble un peu de la magie, mais il a quelques avantages.

  1. L'exécution de vos tests dans le nœud, donc pas de déconner avec le navigateur de l'automatisation.
  2. Moins besoin de désordre AMD réutilisable dans vos tests.
  3. Vous arrivez à utiliser eval dans la colère, et d'imaginer Crockford explose de rage.

Il y a encore quelques inconvénients, évidemment.

  1. Puisque vous êtes des tests dans le nœud, vous ne pouvez pas faire n'importe quoi avec le navigateur d'événements ou de manipulation du DOM. Seulement bon pour les tests de logique.
  2. Encore un peu maladroit. Vous devez simuler out define dans tous les tests, car c'est là que vos tests fait exécuter.

Je suis en train de travailler sur un lanceur de test afin de donner une plus belle syntaxe pour ce genre de choses, mais je n'ai toujours pas la bonne solution pour le problème 1.

Conclusion

Se moquant de deps dans requirejs suce dur. J'ai trouvé un moyen qui sortof fonctionne, mais je suis toujours pas très heureux avec elle. S'il vous plaît laissez-moi savoir si vous avez des meilleures idées.

15voto

Artem Oboturov Points 2292

Il y a un config.map option http://requirejs.org/docs/api.html#config-map.

Sur comment l'utiliser:

  1. Définir normal module;
  2. Définir stub module;
  3. Configurer RequireJS expicitely;

    requirejs.config({
      map: {
        'source/js': {
          'foo': 'normalModule'
        },
        'source/test': {
          'foo': 'stubModule'
        }
      }
    });
    

Dans ce cas, pour le mode normal et le code de test vous pouvez utiliser l' foo module qui sera la véritable référence de module et d'un stub en conséquence.

9voto

janith Points 845

Vous pouvez utiliser testr.js pour se moquer de dépendances. Vous pouvez définir testr à la charge de la maquette dépendances au lieu de l'original. Voici un exemple d'utilisation:

var fakeDep = function(){
    this.getText = function(){
        return 'Fake Dependancy';
    };
};

var Module1 = testr('module1', {
    'dependancies/dependancy1':fakeDep
});

Découvrez ce: http://cyberasylum.janithw.com/mocking-requirejs-dependencies-for-unit-testing/

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