Is there a way to test those kind of middleware in express:
module.exports = function logMatchingUrls(pattern) {
return function (req, res, next) {
if (pattern.test(req.url)) {
console.log('request url', req.url);
req.didSomething = true;
}
next();
}
}
The only middleware testing i found was:
module.exports = function(request, response, next) {
/*
* Do something to REQUEST or RESPONSE
**/
if (!request.didSomething) {
console.log("dsdsd");
request.didSomething = true;
next();
} else {
// Something went wrong, throw and error
var error = new Error();
error.message = 'Error doing what this does'
next(error);
}
};
describe('Middleware test', function(){
context('Valid arguments are passed', function() {
beforeEach(function(done) {
/*
* before each test, reset the REQUEST and RESPONSE variables
* to be send into the middle ware
**/
requests = httpMocks.createRequest({
method: 'GET',
url: '/css/main.css',
query: {
myid: '312'
}
});
responses = httpMocks.createResponse();
done(); // call done so that the next test can run
});
it('does something', function(done) {
/*
* Middleware expects to be passed 3 arguments: request, response, and next.
* We are going to be manually passing REQUEST and RESPONSE into the middleware
* and create an function callback for next in which we run our tests
**/
middleware(responses, responses, function next(error) {
/*
* Usually, we do not pass anything into next except for errors, so because
* in this test we are passing valid data in REQUEST we should not get an
* error to be passed in.
**/
if (error) { throw new Error('Expected not to receive an error'); }
// Other Tests Against request and response
if (!responses.didSomething) { throw new Error('Expected something to be done'); }
done(); // call done so we can run the next test
}); // close middleware
}); // close it
}); // close context
}); // close describe
This work well with the simple middleware (it like testing basic function with callback) provided above but with more complex middleware i cannot get it work. Is it possible to test this kind of middleware?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With