2016-02-05 40 views
18

Sono nuovo a Node ed Express e sto provando a testare i miei percorsi/controller. Ho separato le mie rotte dai miei controller. Come faccio a testare i miei percorsi?Come test unitario Router route

config/express.js

var app = express(); 
    // middleware, etc 
    var router = require('../app/router')(app); 

app/router/index.js

module.exports = function(app) { 
    app.use('/api/books', require('./routes/books')); 
    }; 

app/router/percorsi/books.js

var controller = require('../../api/controllers/books'); 
    var express = require('express'); 
    var router = express.Router(); 

    router.get('/', controller.index); 

    module.exports = router; 

app/API/controller/books.js

// this is just an example controller 
exports.index = function(req, res) { 
    return res.status(200).json('ok'); 
}; 

app/test/API/percorsi/books.test.js

var chai = require('chai'); 
    var should = chai.should(); 
    var sinon = require('sinon'); 

    describe('BookRoute', function() { 

    }); 
+1

Possibile duplicato di [Come funziona un test unitario con Express?] (Http://stackoverflow.com/questions/9517880/how-does-one-unit-test-routes-with-express) – gnerkus

+0

Non è un duplicato , la domanda collegata è per Express precedente che aveva un'API diversa. – Kos

+0

Usa questo [Link] (http://www.designsuperbuild.com/blog/unit_testing_controllers_in_express/) o questo [Link] (http://www.chrisstead.com/archives/1128/unit-testing-express-routing/). –

risposta

1

ho trovato this blog incredibilmente perspicace quando si verifica il mio endpoint dei server.

Nel blog si rivolge:

  • come utilizzare la libreria di test endpoint supertest.

  • Come far ruotare e rimuovere a livello di codice un server express con i percorsi necessari prima e dopo ogni test endpoint. (spiega anche perché vorresti farlo).

  • Come evitare un trucco comune, è necessario memorizzare nella cache i moduli richiesti nei test dell'unità, con conseguenze indesiderate.

Spero che questo aiuti. Buona fortuna e se hai altre domande fammelo sapere.

+3

Il punto del blog contiene alcuni esempi su come utilizzare supertest per testare gli endpoint dell'API. Tuttavia, ritengo che siano necessari alcuni commenti poiché non sono completamente d'accordo con l'autore. Avviare e arrestare il server tra ogni test è un cattivo progetto. Se si tratta di un'API RESTful, stai testando che il server dovrebbe essere senza stato comunque. Se si tratta di un'applicazione con stato, è possibile distruggere la sessione tra ciascun test per ottenere lo stesso risultato. Inoltre, sembra che l'autore non capisca come funziona lo Stack JavaScript che lo porta a conclusioni errate. –

7

Codice:

config/express.js

var app = express(); 
// middleware, etc 
var router = require('../app/router')(app); 

module.exports = app; 

app/test/API/percorsi/books.test.js

var chai = require('chai'); 
var should = chai.should(); 
var sinon = require('sinon'); 
var request = require('supertest'); 
var app = require('config/express'); 

describe('BookRoute', function() { 
    request(app) 
     .get('/api/books') 
     .expect('Content-Type', /json/) 
     .expect('Content-Length', '4') 
     .expect(200, "ok") 
     .end(function(err, res){ 
      if (err) throw err; 
     }); 
}); 

Considerazioni:

Se siete il tuo server richiede uno stato iniziale all'inizio di una serie di test (perché stai eseguendo chiamate che mutano lo stato del server), dovrai scrivere una funzione che restituirà un'app appena configurata e l'inizio di ogni gruppo di test . Esiste una libreria NPM: https://github.com/bahmutov/really-need che ti consentirà di richiedere una versione appena istanziata del tuo server.

1

Questo è interessante perché hai separato i controller dai tuoi router. L'altro articolo di StackOverflow menzionato nei commenti è un buon modo per testare i controller, credo.La cosa da tenere a mente con i test unitari è cosa stai testando esattamente. Non è necessario scrivere test per testare la libreria express perché presumibilmente ha i propri test unitari. Quindi hai solo bisogno di testare le chiamate alla biblioteca. Così, per l'itinerario libri, non vi resta che provare questa una linea di codice:

router.get('/', controller.index); 

mi sono guardato intorno per vedere se ci fosse un modo ovvio per ottenere un elenco di percorsi dalla libreria espresso, ma io didn' ne vedo uno Probabilmente puoi semplicemente controllare la libreria stessa e controllare i suoi interni per vedere se imposti correttamente un percorso. Un'altra opzione è di prenderlo in giro e controllare che lo stiate chiamando correttamente.

Questo sarà molto complicato perché è necessario prendere in esame alcune parti fondamentali di Javascript per testare questa riga di codice. Ecco come ho fatto:

describe('BookRoute', function() { 
    it("should route/to books controller index", function() { 
    var controller = require('../../../api/controllers/books'); 
    var orig_this = this; 
    var orig_load = require('module')._load; 
    var router = jasmine.createSpyObj('Router', ['get']); 
    var express = jasmine.createSpyObj('express', ['Router']); 
    express.Router.and.returnValues(router); 
    spyOn(require('module'), '_load').and.callFake(function() { 
     if (arguments[0] == 'express') { 
     return express; 
     } else { 
     return orig_load.apply(orig_this, arguments); 
     } 
    }); 
    require("../../../router/routes/books"); 
    expect(router.get).toHaveBeenCalledWith('/', controller.index); 
    }); 
}); 

Che cosa sta succedendo qui è che ho usato la funzione spyOn di Jasmine per spyOn la funzione _load in module.js che è quello che gestisce tutte le chiamate richiedono. Questo è così che quando richiediamo il router di libri e le chiamate richiedono ('express') possiamo restituire il nostro espresso SpyObj che abbiamo creato con jasmine.createSpyObj. Una volta che abbiamo sostituito express con il nostro oggetto spia, possiamo farlo restituire il nostro Router SpyObj che ci permetterà di spiare router.get. Quindi possiamo verificare che sia chiamato con '/' e controller.index.

Questo potrebbe probabilmente essere trasformato in una sorta di utilità se si volesse usarlo molto.

Solitamente evito molte cose usando un approccio più orientato agli oggetti e sto passando intorno ad alcuni oggetti ovunque che posso prendere in giro per i test o potresti usare una specie di iniezione di dipendenza come Angular.