2012-03-05 13 views
6

Sto lottando per scrivere test di alta qualità intorno ai miei moduli di nodo. Il problema è il sistema del modulo richiesto. Voglio essere in grado di verificare che un determinato modulo richiesto abbia un metodo o il suo stato sia cambiato. Sembrano esserci 2 librerie relativamente piccole che possono essere utilizzate qui: node-gently e mockery. Tuttavia, a causa del loro "profilo" basso, mi viene da pensare che le persone non lo testano, oppure esiste un altro modo per farlo, di cui non sono a conoscenza.Test di Node.js, mock out e testare un modulo che è stato richiesto?

Qual è il modo migliore per prendere in giro e testare un modulo che è stato richiesto?

risposta

10

----------- UPDATE ---------------

node-sandbox opere sugli stessi principi sotto enunciati, ma è racchiuso in un bel modulo. Sto trovando molto bello lavorare con.


--------------- awnser dettagliata ---------------

Dopo molti tentativi ho ha trovato il modo migliore per testare i moduli dei nodi in isolamento mentre sbeffeggiava le cose è usare il metodo di Vojta Jina per eseguire ogni modulo all'interno di un vm con un nuovo contesto come spiegato here.

con questo modulo vm test:

var vm = require('vm'); 
var fs = require('fs'); 
var path = require('path'); 

/** 
* Helper for unit testing: 
* - load module with mocked dependencies 
* - allow accessing private state of the module 
* 
* @param {string} filePath Absolute path to module (file to load) 
* @param {Object=} mocks Hash of mocked dependencies 
*/ 
exports.loadModule = function(filePath, mocks) { 
    mocks = mocks || {}; 

    // this is necessary to allow relative path modules within loaded file 
    // i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some 
    var resolveModule = function(module) { 
    if (module.charAt(0) !== '.') return module; 
    return path.resolve(path.dirname(filePath), module); 
    }; 

    var exports = {}; 
    var context = { 
    require: function(name) { 
     return mocks[name] || require(resolveModule(name)); 
    }, 
    console: console, 
    exports: exports, 
    module: { 
     exports: exports 
    } 
    }; 

    vm.runInNewContext(fs.readFileSync(filePath), context); 
    return context; 
}; 

è possibile testare ogni unità con il proprio contesto e facilmente spegnere tutti dependencys esterni.

fsMock = mocks.createFs(); 
mockRequest = mocks.createRequest(); 
mockResponse = mocks.createResponse(); 

// load the module with mock fs instead of real fs 
// publish all the private state as an object 
module = loadModule('./web-server.js', {fs: fsMock}); 

Consiglio vivamente questo modo di scrivere test efficaci isolati. Solo i test di accettazione dovrebbero colpire l'intero stack. I test di unità e integrazione dovrebbero testare parti isolate del sistema.

+0

Grazie per l'ottima risposta! Comunque ho un'altra domanda: Non ero in grado di sfruttare questa tecnica per scavalcare le funzioni private con quelle personalizzate nel modulo in fase di test. ha come risultato due funzioni: una nell'ambito locale e un'altra nell'ambito globale, con il modulo in prova che chiama sempre la versione globale/originale. – Attilah

5

Penso che il modello di derisione sia eccellente. Detto questo, di solito scelgo di inviare dipendenze come parametri a una funzione (simile alle dipendenze di passaggio nel costruttore).

// foo.js 
module.exports = function(dep1, dep2) { 
    return { 
     bar: function() { 
      // A function doing stuff with dep1 and dep2 
     } 
    } 
} 

Durante il test, posso inviare mock, oggetti vuoti invece, qualsiasi cosa sia appropriata. Nota che non lo faccio per tutte le dipendenze, fondamentalmente solo IO - Non sento il bisogno di testare che il mio codice chiama path.join o qualsiasi altra cosa.

penso che il "basso profilo" che sta facendo si nervoso è a causa di un paio di cose:

  • Alcune persone strutturano il loro codice simile al mio
  • Alcune persone hanno il loro aiuto compiere la stessa obiettivo come mockery et al (è un modulo molto semplice)
  • Alcune persone non eseguono il test dell'unità, ma girano su un'istanza della loro app (e db, ecc.) e le mettono alla prova. Test di pulizia e il server è così veloce che non influisce sulle prestazioni del test.

In breve, se pensi che la presa in giro sia giusta per te, prova!

+0

Il problema di questo è il test di unità sta colpendo il database che non è ideale. –

+1

@beck: solo se si invia un db reale durante il test. –

1

potete facilmente deridere richiede utilizzando "a": https://npmjs.org/package/a

//Example faking require('./foo') in unit test: 
var fakeFoo = {}; 
var expectRequire = require('a').expectRequire; 
expectRequire('./foo).return(fakeFoo); 


//in sut: 
var foo = require('./foo); //returns fakeFoo 
Problemi correlati