express middleware testing mocha chai
Here's a simple setup that you could use, using chai
and sinon
:
var expect = require('chai').expect;var sinon = require('sinon');var middleware = function logMatchingUrls(pattern) { return function (req, res, next) { if (pattern.test(req.url)) { console.log('request url', req.url); req.didSomething = true; } next(); }}describe('my middleware', function() { describe('request handler creation', function() { var mw; beforeEach(function() { mw = middleware(/./); }); it('should return a function()', function() { expect(mw).to.be.a.Function; }); it('should accept three arguments', function() { expect(mw.length).to.equal(3); }); }); describe('request handler calling', function() { it('should call next() once', function() { var mw = middleware(/./); var nextSpy = sinon.spy(); mw({}, {}, nextSpy); expect(nextSpy.calledOnce).to.be.true; }); }); describe('pattern testing', function() { ... });});
From there, you can add more elaborate tests for the pattern matching, etc. Since you're only using req.url
, you don't have to mock an entire Request
object (as created by Express) and you can just use a simple object with a url
property.
I used node-mocks-http to unit test my middleware. Here's my code:
function responseMiddleware(req, res, next) { res.sendResponse = (...args) => { //<==== Code removed from here }; next();}
And in my spec file I did it like this:
var expect = require('chai').expect;var sinon = require('sinon'); var responseMiddleware = require('./response');var httpMocks = require('node-mocks-http'); describe('request handler calling', function() { it('should call next() once', function() { var nextSpy = sinon.spy(); responseMiddleware({}, {}, nextSpy); expect(nextSpy.calledOnce).to.be.true; }); it('should add sendResponse key', function() { var nextSpy = sinon.spy(); var req = httpMocks.createRequest(); var res = httpMocks.createResponse(); responseMiddleware(req, res, nextSpy); expect(nextSpy.calledOnce).to.be.true; responseMiddleware(req, res, () => { expect(res).to.have.property('sendResponse'); }) }); });
If you are using async calls then you can use await and then call done() after that.