2013-03-10 6 views
17

Ich schreibe derzeit einige Tests für eine Nodejs-Anwendung. davon ausgehen, dass ich ein Modul wie diese:Wie Unit Test 'private' Dienstprogramm Funktion in Nodejs

module.exports = function myModule(moduleParam) { 
    var someVar; 
    .... 
    .... 
    function helper(param) { 
     return param + someVar; 
    } 
    return { 
     doSomething: function (bar) { 
      .... 
      .... 
      var foo = helper(bar); 
      .... 
      .... 
     } 
    }; 
}; 

Angenommen, die ‚Helfer‘ Funktion nur innerhalb des Moduls nützlich ist und nicht nach außen freigelegt werden soll.

Was ist die "beste Praxis" zum Testen? (Natürlich kann ich die DoSomething-Funktion als Ganzes testen, aber auf diese Weise wird die "Helfer" -Funktion in einer bestimmten Situation in einer "Black-Box" -Methode getestet).

Ich benutze nodeunit als Test-Framework, für diese Metter, aber ich kann es bei Bedarf ändern.

+0

I don Ich denke, Sie können es überhaupt testen, da Sie dafür auf die lokalen Variablen zugreifen müssen. – Bergi

+0

Sie könnten schreiben eine Funktion, die nur eine Funktion an Exports anfügt, wenn Sie tatsächlich Tests ausführen? – phenomnomnominal

+0

@phenomnomnominal, meinst du etwas wie eine Funktion exportiert nur wenn einige 'Test' globale Variable definiert ist oder so etwas? – ArtoAle

Antwort

22

Sie testen es nicht. Unit-Tests sind Black-Box-Tests. Dies bedeutet, dass das einzige, was Sie testen, ist die öffentliche Schnittstelle aka Vertrag.

Private Funktionen wie diese können nur aus dem Refaktorieren von öffentlichen erfolgen.

Also, wenn Sie konsequent TDD verwenden, werden Ihre privaten Funktionen implizit getestet.

Wenn sich das falsch anfühlt, liegt es meistens daran, dass Ihre Struktur falsch ist. Dann sollten Sie darüber nachdenken, Ihre privaten Sachen zu einem zusätzlichen Modul zu bewegen.

+1

Das war, was ich dachte (und für andere - mehr wiederverwendbare - Funktionen). Ich stimme nicht zu, dass diese nur vom Refactoring kommen können ... kommt eine private Java-Methode nur aus dem Refactoring von öffentlichen heraus? Ich denke nicht ... jedenfalls denke ich, dass die Strategie "Move to a Module" akzeptabel sein könnte, ich habe nur Zweifel an der Auflösung des Scoping, die zugunsten der Weitergabe von Abhängigkeiten verloren geht. Ich bin mir nicht sicher, dass es immer so ist eine gute Sache – ArtoAle

+0

Wenn Sie streng nach TDD verfahren, wird auch in Java jede private Methode nur das Ergebnis eines Refactorings einer (oder mehrerer) öffentlicher Methoden sein. Aber wie auch immer, ich denke, das ist der Weg zu gehen :-) –

+0

Ich war mir dieser strengen Definition nicht bewusst :) In diesem Begriff denke ich, dass du die Antwort als korrekt angesehen hast. Kannst du mir bitte einige Links zeigen, wo diese Art von OK 'Aussage' über TDD zu finden ist? Dank – ArtoAle

8

Da ich Tests als ein nützliches Tool jenseits der Unit-Tests und TDD (this SO answer macht ein gutes Argument) finden, habe ich ein Npm-Paket, um in Fällen wie Ihnen helfen: require-from.

In Ihrem Beispiel ist dies, wie Sie es verwenden würde:

Modul-file.js:

function helper(param) { 
    return param + someVar; 
} 

module.exports = function myModule(moduleParam) { 
    var someVar; 
    .... 
    .... 
    return { 
     doSomething: function (bar) { 
      .... 
      .... 
      var foo = helper(bar); 
      .... 
      .... 
     } 
    }; 
}; 
module.helperExports = helper; 

Import-file.js:

var requireFrom = require('require-from'); 
var helper = requireFrom('helperExports', './module-file')); 
var public = requireFrom('exports', './module-file')); // same as require('./module-file') 
+0

Mmm ...nicht wirklich meine Frage :) Ich meine - ich stimme zu, dass Ihr Werkzeug nützlich ist, da es "öffentliche" von "privaten" Exporten trennt - aber meine Frage war mehr darüber, wie man diese Situation in TDD angehen kann - ich verstehe, dass Sie Affe-Patch Alles, ich wollte wissen, ob es eine gute Praxis gibt, Code zu schreiben, und um ehrlich zu sein, etwas explizit zum Exportieren zu exportieren ist etwas, das ich nicht wirklich mag, da ich TDD eher als eine Anleitung ansehe schreibe besser, mehr wiederverwendbaren Code :) – ArtoAle

+0

Best Practices, wie Muster, hängen von den Umständen ab. Der Entwickler muss immer noch die Kompromisse in Betracht ziehen und ein Urteil fällen. Angesichts der Tatsache, dass es sinnvoll ist, Funktionalitätseinheiten isoliert zu testen, eine stabile öffentliche API zu erhalten und zu minimieren, was verfügbar ist, bietet die Bibliothek eine Alternative zum Extrahieren von Code in ein separates Modul. Beispiel: Sie möchten verwandten Code zusammenhalten oder das Risiko vermeiden, dass andere Module vom extrahierten Code abhängig sind (dies geschieht in größeren Teams). Auch wenn die Antwort für Sie jetzt nicht nützlich ist, könnte es in der Zukunft oder für andere Leute sein. – DEADB17

+0

BTW: Es gibt keine Affepatching beteiligt. Der Mechanismus entspricht dem regulären Knotenexport. – DEADB17