proyecto node how crear node.js express

node.js - how - node js install express windows



¿Cómo puede una unidad probar las rutas con Express? (7)

Estoy en el proceso de aprender Node.js y he estado jugando con Express . Realmente me gusta el marco; sin embargo, tengo problemas para descifrar cómo escribir una unidad / prueba de integración para una ruta.

Poder probar módulos simples es fácil y lo hemos estado haciendo con Mocha ; sin embargo, mis pruebas de unidad con Express fallan porque el objeto de respuesta que paso no retiene los valores.

Route-Function Under Test (routes / index.js):

exports.index = function(req, res){ res.render(''index'', { title: ''Express'' }) };

Módulo de prueba unitaria:

var should = require("should") , routes = require("../routes"); var request = {}; var response = { viewName: "" , data : {} , render: function(view, viewData) { viewName = view; data = viewData; } }; describe("Routing", function(){ describe("Default Route", function(){ it("should provide the a title and the index view name", function(){ routes.index(request, response); response.viewName.should.equal("index"); }); }); });

Cuando ejecuto esto, falla por "Error: filtraciones globales detectadas: viewName, data".

  1. ¿Dónde me estoy equivocando para poder hacer que esto funcione?

  2. ¿Hay alguna manera mejor para que yo pruebe mi código en este nivel?

Actualización 1. Fragmento de código corregido desde que olvidé "it ()".


Cambia tu objeto de respuesta:

var response = { viewName: "" , data : {} , render: function(view, viewData) { this.viewName = view; this.data = viewData; } };

Y funcionará.


Como otros han recomendado en los comentarios, parece que la forma canónica de probar los controladores Express es a través de supertest .

Un ejemplo de prueba podría verse así:

describe(''GET /users'', function(){ it(''respond with json'', function(done){ request(app) .get(''/users'') .set(''Accept'', ''application/json'') .expect(200) .end(function(err, res){ if (err) return done(err); done() }); }) });

Upside: puedes probar toda tu pila de una vez.

Desventaja: se siente y actúa como una prueba de integración.


La forma más fácil de probar HTTP con Express es robar el ayudante http de TJ

Yo personalmente uso su ayudante

it("should do something", function (done) { request(app()) .get(''/session/new'') .expect(''GET'', done) })

Si desea probar específicamente el objeto de su ruta, pase las imitaciones correctas

describe("Default Route", function(){ it("should provide the a title and the index view name", function(done){ routes.index({}, { render: function (viewName) { viewName.should.equal("index") done() } }) }) })


Llegué a la conclusión de que la única forma de probar aplicaciones unitarias realmente es mantener una gran separación entre los manejadores de solicitudes y su lógica central.

Por lo tanto, su lógica de aplicación debe estar en módulos separados que pueden ser require y probados en unidades, y tienen una dependencia mínima de las clases de Solicitud y Respuesta Expresas como tales.

Luego, en los manejadores de solicitudes debe llamar a los métodos apropiados de sus clases de lógica central.

Pondré un ejemplo una vez que termine de reestructurar mi aplicación actual.

Supongo que algo como this? (Siéntase libre de compartir la esencia o comentar, todavía estoy explorando esto).

Editar

Aquí hay un pequeño ejemplo, en línea. Vea this? para un ejemplo más detallado.

/// usercontroller.js var UserController = { _database: null, setDatabase: function(db) { this._database = db; }, findUserByEmail: function(email, callback) { this._database.collection(''usercollection'').findOne({ email: email }, callback); } }; module.exports = UserController; /// routes.js /* GET user by email */ router.get(''/:email'', function(req, res) { var UserController = require(''./usercontroller''); UserController.setDB(databaseHandleFromSomewhere); UserController.findUserByEmail(req.params.email, function(err, result) { if (err) throw err; res.json(result); }); });


Me preguntaba esto también, pero específicamente para pruebas unitarias y no pruebas de integración. Esto es lo que estoy haciendo ahora,

test(''/api base path'', function onTest(t) { t.plan(1); var path = routerObj.path; t.equals(path, ''/api''); }); test(''Subrouters loaded'', function onTest(t) { t.plan(1); var router = routerObj.router; t.equals(router.stack.length, 5); });

Donde el routerObj es solo {router: expressRouter, path: ''/api''} . Luego cargo en subrouters con var loginRouterInfo = require(''./login'')(express.Router({mergeParams: true})); y luego la aplicación expresa llama a una función init teniendo en cuenta el enrutador expreso como parámetro. El initRouter luego llama a router.use(loginRouterInfo.path, loginRouterInfo.router); montar el subrouter

El subrouter se puede probar con:

var test = require(''tape''); var routerInit = require(''../login''); var express = require(''express''); var routerObj = routerInit(express.Router()); test(''/login base path'', function onTest(t) { t.plan(1); var path = routerObj.path; t.equals(path, ''/login''); }); test(''GET /'', function onTest(t) { t.plan(2); var route = routerObj.router.stack[0].route; var routeGetMethod = route.methods.get; t.equals(routeGetMethod, true); var routePath = route.path; t.equals(routePath, ''/''); });


Para lograr pruebas unitarias en lugar de pruebas de integración, me burlé del objeto de respuesta del controlador de solicitudes.

/* app.js */ import endpointHandler from ''./endpointHandler''; // ... app.post(''/endpoint'', endpointHandler); // ... /* endpointHandler.js */ const endpointHandler = (req, res) => { try { const { username, location } = req.body; if (!(username && location)) { throw ({ status: 400, message: ''Missing parameters'' }); } res.status(200).json({ location, user, message: ''Thanks for sharing your location with me.'', }); } catch (error) { console.error(error); res.status(error.status).send(error.message); } }; export default endpointHandler; /* response.mock.js */ import { EventEmitter } from ''events''; class Response extends EventEmitter { private resStatus; json(response, status) { this.send(response, status); } send(response, status) { this.emit(''response'', { response, status: this.resStatus || status, }); } status(status) { this.resStatus = status; return this; } } export default Response; /* endpointHandler.test.js */ import Response from ''./response.mock''; import endpointHandler from ''./endpointHander''; describe(''endpoint handler test suite'', () => { it(''should fail on empty body'', (done) => { const res = new Response(); res.on(''response'', (response) => { expect(response.status).toBe(400); done(); }); endpointHandler({ body: {} }, res); }); });

Luego, para lograr las pruebas de integración, puede burlarse de su endpointHandler y llamar al endpoint con supertest .


si la unidad de prueba con Express 4 nota este ejemplo de gjohnson :

var express = require(''express''); var request = require(''supertest''); var app = express(); var router = express.Router(); router.get(''/user'', function(req, res){ res.send(200, { name: ''tobi'' }); }); app.use(router); request(app) .get(''/user'') .expect(''Content-Type'', /json/) .expect(''Content-Length'', ''15'') .expect(200) .end(function(err, res){ if (err) throw err; });