Ensuring Express App is running before each Mocha Test Ensuring Express App is running before each Mocha Test mongoose mongoose

Ensuring Express App is running before each Mocha Test


I am late to the party, but I found the best way to set up my mocha test suite for an express app is to make my app.js or server.js file export the app object, like this:

var mongoose = require('mongoose');var express = require('express');require('express-mongoose');var env = process.env.NODE_ENV || 'development';var config = require('./config/config')[env];var models = require('./app/models');var middleware = require('./app/middleware');var routes = require('./app/routes');var app = express();app.set('port', process.env.PORT || config.port || 3000);app.set('views', __dirname + '/app/views');app.set('view engine', 'jade');// databasemongoose.connect(config.db);// middlewaremiddleware(app);// Application routesroutes(app);app.listen(app.get('port'));console.log('Express server listening on port ' + app.get('port'));// export app so we can test itexports = module.exports = app;

make sure your config file has different environments like development, test, production set up:

var path = require('path');var rootPath = path.normalize(__dirname + '/..');module.exports = {  development: {    db: 'mongodb://localhost/my_dev_db',    port: 3000  },  test: {    db: 'mongodb://localhost/my_test_db',    port: 8888  },  production: {    // ...  }}

then in your test files you can go ahead and require your app, which will connect to the right db and on the right port:

var should = require('chai').should();var request = require('supertest');var mongoose = require('mongoose');var app = require('../app');var agent = request.agent(app);var User = mongoose.model('User');    // get users    describe('GET /api/users', function() {      it('returns users as JSON', function(done) {        agent        .get('/api/users')        .expect(200)        .expect('Content-Type', /json/)        .end(function(err, res) {          if (err) return done(err);          res.body.should.have.property('users').and.be.instanceof(Array);          done();        });      });    });

And finally, to start up the whole monster you include this in your package.json (make sure to have nodemon and mocha in your devDependencies):

"scripts": {    "start": "NODE_ENV=development ./node_modules/.bin/nodemon app.js",    "test": "NODE_ENV=test ./node_modules/.bin/mocha --reporter spec test/**.js"  }

Now you can start your test suite with npm test and your app with npm start.

Hope it helps!ps: most of the stuff I learned from looking at this amazing example: https://github.com/madhums/node-express-mongoose-demo


I ran into the same issue while using jasmine/supertest to test my express app. I solved the issue by emitting when the app was ready and only running my tests afterwards. Here is my directory structure

- server.js- spec    - setup.spec.js    - test.spec.js

In server.js when ever your server is set up and you are ready to run your tests add app.emit('started');. And make sure to export your app! In setup.spec.js you can watch for the event to be emitted.

server.js

const express = require('express');const app = express();module.exports = app; // for testingsetTimeout(() => {    app.listen(process.env.PORT || 3000);});

setup.spec.js

const server = require('../index');beforeAll(done => server.on('started', done));

test.spec.js

const request = require('supertest');const server = require('../index');describe('test', () => {    it('test server works', done => {        request(server).get('/test').expect(200);     });});

The same idea should work for mocha as well. Here is an article explaining this for mocha. You should just change beforeAll to before.


There might be a more straightforward way, but I went to Grunt for automating my functional tests. There's an express and mocha plugin to reach your goal. My gruntfile:

'use strict';module.exports = function (grunt) {grunt.initConfig({    express: {        options: {}      , test: {            options: {                script: './app.js'            }        }    }  , simplemocha: {        options: {            globals: ['should']          , timeout: 8000          , ignoreLeaks: false          , ui: 'bdd'          , reporter: 'tap'        }      , all: { src: ['tests/*.test.js'] }    }})grunt.loadNpmTasks('grunt-express-server')grunt.loadNpmTasks('grunt-simple-mocha')grunt.registerTask('default', ['express:test', 'simplemocha', 'express:test:stop'])}

bonus: add 'grunt' as a git pre-commit hook. This way you cannot commit without passing all the tests