I'm in the process of learning Node.js and have been playing around with Express. Really like the framework;however, I'm having trouble figuring out how to write a unit/integration test for a route.
Being able to unit test simple modules is easy and have been doing it with Mocha; however, my unit tests with Express fail since the response object I'm passing in doesn't retain the values.
Route-Function Under Test (routes/index.js):
exports.index = function(req, res){ res.render('index', { title: 'Express' }) };
Unit Test Module:
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"); }); }); });
When I run this, it fails for "Error: global leaks detected: viewName, data".
Where am I going wrong so that I can get this working?
Is there a better way for me to unit test my code at this level?
Update 1. Corrected code snippet since I initially forgot "it()".
A route is a section of Express code that associates an HTTP verb ( GET , POST , PUT , DELETE , etc.), a URL path/pattern, and a function that is called to handle that pattern.
If you are using react router dom, then there are two ways to test the routes using jest. One way is to create an object containing the pathname of route as key and component name for that route as value, and then do an assertion based on that object.
As others have recommended in comments, it looks like the canonical way to test Express controllers is through supertest.
An example test might look like this:
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: you can test your entire stack in one go.
Downside: it feels and acts a bit like integration testing.
I've come to the conclusion that the only way to really unit test express applications is to maintain a lot of separation between the request handlers and your core logic.
Thus, your application logic should be in separate modules that can be require
d and unit tested, and have minimal dependence on the Express Request and Response classes as such.
Then in the request handlers you need to call appropriate methods of your core logic classes.
I'll put an example up once I've finished restructuring my current app!
I guess something like this? (Feel free to fork the gist or comment, I'm still exploring this).
Edit
Here's a tiny example, inline. See the gist for a more detailed example.
/// 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); }); });
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