2012-06-10 16 views
15

Sto provando a creare una suite di test standalone usando mocha, che in un mondo perfetto dovrebbe avviare la mia applicazione express.js, usare zombie per eseguire il rendering di una pagina, controllare un gruppo di cose e poi teardown/kill l'applicazione express.js.Setup/teardown dell'applicazione express.js con la moka

C'è un modo semplice/migliore per farlo?

NB. Potrei avere il server delle applicazioni express in esecuzione prima di eseguire i test, ma a che serve Yaks se non li raderai.

+2

Nizza domanda.Io stesso l'ho esaminato per un po ', ma dopo una settimana mi sono arreso. Ho trovato zombi davvero fastidiosi con cui lavorare. Ho letto molto su PhantomJS ma non l'ho provato da solo. – Pickels

risposta

23

Innanzitutto, è necessario spostare la configurazione effettiva dell'app in un modulo e importarla nel file che avvia effettivamente l'app. Ora che questo è separato, puoi avere l'app nel suo stato completo prima di ascoltarlo realmente.

Dovresti spostare la configurazione attuale della tua app in un file separato, chiamiamola app.js, puoi chiamare ascoltare dal file su cui hai eseguito il nodo, chiamiamola index.js.

Quindi, app.js sarà simile:

var express = require('express') 
    , routes = require('./routes'); 

var app = module.exports = express.createServer(); 

// Configuration 

app.configure(function(){ 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 

app.configure('development', function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

// Routes 

app.get('/', routes.index); 

e index.js sarà simile:

var app = require('./app'); 

app.listen(3000, function(){ 
    console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); 
}); 

Questo separa il caricamento della vostra app dalla realtà averlo ascoltare, che consente di carica quell'app nei tuoi test unitari.

Nei test di unità, si farebbe qualcosa con un metodo di installazione e un metodo di smontaggio per richiamare e far cadere il server.

nel test di file/app_tests.js:

describe('app', function(){ 
    var app = require('../app'); 
    beforeEach(function(){ 
    app.listen(3000); 
    }); 
    // tests here 
    afterEach(function(){ 
    app.close(); 
    }) 
}); 
+0

Fantastico! Ma, nel mio caso, ho più file di test e sembra che mocha esegua tutti i file contemporaneamente, il che causa alcuni conflitti tra i file di test! cosa posso fare ? –

+0

Effettua l'ascolto di ogni test su una porta diversa: scegli un numero casuale (abbastanza alto) –

+0

SOLUZIONE ECCELLENTE! Questo è il modo giusto per farlo. Una modifica: dovresti in realtà chiudere il risultato di app.listen, non app stessa, cioè: (in beforeEach) "instance = app.listen (3000);" ... e poi (in afterEach) "instance.close()" –

4

Oltre a Oved D risposta.

Descrivi la tua app in veloce-app.js o qualche altro file:

module.exports = function (o) { 
    o = o || {}; 
    var app = express(); 

    // app.configure 
    // configure routes 
    if (o.someOption) { 
    // some additional test code 
    } 

    return app; 
} 

descrivono i test in test/01-some.js:

var expressApp = require('../express-app'); 
describe('some', function() { 

    // just describe needed vars 
    var app, server, port; 

    // describe setup 
    before(function (next) { 
    // create app when 
    app = expressApp({routes: /api\/some\/.*/ /* put here some test options ...*/}); 
    // creating listener with random port 
    server = app.listen(function() { 
     // store port when it ready 
     port = server.address().port; 
     // and go to tests 
     next(); 
    }); 
    }); 

    // tests 
    it('should return valid result', function (done) { 
    // do a simple request to /api/some 
    http.request({ 
     host: 'localhost', 
     port: port, 
     path: '/api/some' 
    }, function (res) { 
     if (res.err) throw new Error(res.err); 
     done(); 
    }); 
    }); 

    // teardown 
    after(function() { 
    // stop listening that port 
    server.close(); 
    }); 

}); 

Fatto. ;-)

Ora è possibile creare qualsiasi numero di test del genere. Ti consigliamo di abilitare solo gli URL e i servizi necessari nei test definendoli passando i parametri al modulo express-app.js.


Aggiornamento:

Non so come funziona in mocha ma meglio spostare before e after chiamate a init.js e caricarlo con mocha --require init.js.

file dovrebbe apparire così:

// use it in your mocha tests 
global.setupEnv = function setupEnv (o, before, after) { 

    // just describe needed vars 
    var env = Object.create(null); 

    // setup 
    before(function (next) { 
     // create app 
     env.app = expressApp(o); 
     // creating listener with random port 
     env.server = env.app.listen(function() { 
      // store port when it ready 
      port = env.server.address().port; 
      env.app.log('Listening on ', env.port); 
      // and go to tests 
      next(); 
     }); 
    }); 

    // teardown 
    after(function() { 
     // stop listening that port 
     env.server.close(); 
    }); 

    return env; 
} 

E nei test:

// requiring dependencies 
var request = require('request'); 

describe('api', function() { 

    // describe setup 
    var env = global.setupEnv({ 
      routes: 'api/some' 
     }, before, after); 

    // tests 
    it('should pass', function (done) { 
     request('http://localhost:' + env.port, function (error, response, body) { 
      done(); 
     }); 
    }); 

});