Comment faire pour tester un module node.js qui requiert d'autres modules

C'est un exemple trivial qui illustre l'essentiel de mon problème:

var innerLib = require('./path/to/innerLib'); function underTest() { return innerLib.doComplexStuff(); } module.exports = underTest; 

J'essaie d'écrire un test unitaire pour ce code. Comment puis-je innerLib l'exigence pour le innerLib sans se moquer complètement de la fonction requise?

EDIT: Donc, c'est moi qui essayons de faire la différence avec le besoin global et de découvrir qu'il ne fonctionnera pas même pour ce faire:

 var path = require('path'), vm = require('vm'), fs = require('fs'), indexPath = path.join(__dirname, './underTest'); var globalRequire = require; require = function(name) { console.log('require: ' + name); switch(name) { case 'connect': case indexPath: return globalRequire(name); break; } }; 

Le problème est que la fonction requise dans le fichier underTest.js n'a pas été simulée. Il indique toujours la fonction requise à l'échelle mondiale. Donc, il me semble que je ne peux que me moquer de la fonction require dans le même fichier, je me moque. Si j'utilise le Global require pour inclure quoi que ce soit, même après avoir surchargé la copie locale, les fichiers requis seront encore require .

Tu peux maintenant!

J'ai publié proxyquire qui prendra soin de remplacer l'exigence globale dans votre module pendant que vous l' éprouvez .

Cela signifie que vous n'avez besoin d' aucune modification de votre code afin d'injecter des maquettes pour les modules requis.

Proxyquire a un api très simple qui permet de résoudre le module que vous essayez de tester et de transmettre les moches / stubs pour ses modules requis en une seule étape.

@Raynos est juste que, traditionnellement, vous avez dû recourir à des solutions pas très idéales pour réaliser cela ou faire un développement ascendant à la place

Quelle est la raison principale pour laquelle j'ai créé proxyquire – pour permettre un développement top-down test driven sans tracas.

Consultez la documentation et les exemples afin de déterminer si cela correspond à vos besoins.

Une meilleure option dans ce cas est de simuler les méthodes du module qui sont renvoyées.

Pour le meilleur ou pour le pire, la plupart des modules node.js sont des singletons; Deux morceaux de code qui nécessitent () le même module obtenez la même référence à ce module.

Vous pouvez exploiter cela et utiliser quelque chose comme sinon pour se moquer des éléments requis. Le test de moka suit:

 // in your testfile var innerLib = require('./path/to/innerLib'); var underTest = require('./path/to/underTest'); var sinon = require('sinon'); describe("underTest", function() { it("does something", function() { sinon.stub(innerLib, 'toCrazyCrap', function() { // whatever you would like innerLib.toCrazyCrap to do under test }); underTest(); sinon.assert.calledOnce(innerLib.toCrazyCrap); // sinon assertion innerLib.toCrazyCrap.restore(); // restore original functionality }); }); 

Sinon a une bonne intégration avec chai pour faire des assertions, et j'ai écrit un module pour intégrer sinon avec mocha pour permettre un nettoyage plus facile des espions / stub (pour éviter la pollution des tests).

Notez que UnderTest ne peut pas être moqué de la même manière, car underTest ne retourne qu'une fonction.

J'utilise un jeu de simulation . Assurez-vous de définir vos faiblesses avant d' require le module soit testé.

Vous ne pouvez pas. Vous devez construire votre unité de test d'unité afin que les modules les plus bas soient testés en premier et que les modules de niveau supérieur nécessitant des modules soient testés ultérieurement.

Vous devez également supposer que tout code de tiers et node.js lui-même est bien testé.

Je présume que vous verrez des cadres moqueurs arriver dans un proche avenir qui global.require

Si vous devez vraiment vous moquer, vous pouvez modifier votre code pour exposer la portée modulaire.

 // underTest.js var innerLib = require('./path/to/innerLib'); function underTest() { return innerLib.toCrazyCrap(); } module.exports = underTest; module.exports.__module = module; // test.js function test() { var underTest = require("underTest"); underTest.__module.innerLib = { toCrazyCrap: function() { return true; } }; assert.ok(underTest()); } 

Soyez averti de cela expose .__module dans votre API et tout code peut accéder à la portée modulaire sous son propre danger.