How to test ExpressJS route and "controller" separately
I have an Express route defined like this (where app
is my Express app):
module.exports = function(app) {
var controller = require('../../app/controllers/experiment-schema');
app.route('/api/experiment-schemas/random').get(controller.random);
};
In this "controller" file, I have this method:
exports.random = function (req, res, callback) {
ExperimentSchema.count({}, function (err, count) {
var rand = Math.floor(Math.random() * count);
ExperimentSchema.find({})
.skip(rand)
.limit(1)
.populate('mediaPool', 'artist title label')
.exec(function (err, schema) {
res.json(200, schema);
if (typeof callback === 'function') {
callback();
}
});
});
}
Here ExperimentSchema
is Mongoose model. Since the controller method hits the database, I pass a callback in my test so that I can wait for these requests to return to the database and check the return value. I am doing this based on this question .
When I go to test a route, I test supertest
by actually making an HTTP call to the route. The problem is that when I do this, Express injects next
as the third argument into my method random
. Now, callback()
aliases next()
, and things go hard. How can I check my route and my controller separately?
I fixed this by refactoring the route to only expect the default parameters req
and res
.
The best way to test such controller functionality is to simply mock the request and response data and export it to a test suite like mocha. Though it seems like you will also need to mock your mongoose schema. There is no easy way to test these components unless you want to mock the inputs for these functions.