How to export node express app for chai-http How to export node express app for chai-http mongodb mongodb

How to export node express app for chai-http


After receiving some good feedback, I found this solution works best for me, based on Gomzy's answer and Vikash Singh's answer.

In server.js I'm connecting to the mongo pool, then emitting the 'ready' event on the express app. Then in the test, I can use before() to wait for 'ready' event to be emitted on the app. Once that happens, I'm good to start executing the test.

server.js

import express from 'express';import bodyParser from 'body-parser';import MongoPool from './lib/MongoPool';let app = express();let port = process.env.PORT || 5000;app.use(bodyParser.urlencoded({ extended: false }));app.use(bodyParser.json());(async () => {    await MongoPool.connect();    console.log("Connected to db.");    require('./api').default(app);    app.listen(port, () => {        console.log(`Listening on port ${port}.`)        app.emit("ready");    });})();export default app;

test.js

//Require the dev-dependenciesimport chai from 'chai';import chaiHttp from 'chai-http';import server from '../src/server'; let should = chai.should();chai.use(chaiHttp);before(done => {  server.on("ready", () => {    done();  })})describe('Forecast', () => {  describe('/GET forecast', () => {    it('it should GET the forecast', (done) => {      chai.request(server)          .get('/api/forecast?type=grid&lat=39.2667&long=-81.5615')          .end((err, res) => {              res.should.have.status(200);            done();          });    });  });});


Express app is an instance of EventEmitter so we can easily subscribe to events. i.e app can listen for the 'ready' event.

Your server.js file will look like below,

import express from 'express';import api from './api';import MongoPool from './lib/MongoPool';let app = express();let port = process.env.PORT || 3000;app.on('ready', function() {  app.listen(3000, function() {    console.log('app is ready');  });});MongoPool.connect((err, success) => {  if (err) throw err;  if (success) {    console.log('Connected to db.');    // apply express router endpoints to app    api(app);    // All OK - fire (emit) a ready event.    app.emit('ready');  } else {    throw 'Couldnt connect to db';  }});export default app;


Just create a function below to connect to mongo and, make it returns a promise.then use await to wait for it to connect and return. the function could be like that

function dbconnect(){    return new Promise(function(resolve, reject){    MongoPool.connect((err, success) => {    if (err) reject(err);    if (success) {        resolve({'status' : true})    } else {        reject(new Error({'status' : false}))    }})    })}

And then, use

await dbconnect();api(app);app.listen(port, () => {    console.log(`App listening on port ${port}`);})

now await line will wait for the function to connect to DB and then return success or error in case of failure.This is a kind of solution you can use, but I would not recommend you to do this, what we actually do is.

create services and use those services in routes, don't write DB code directly in routes.

and

while writing tests for routes mock/stub those services, and test services separately in other test cases, where you just pass DB object and service will add functions on that DB objects, so in tests you can connect to DB and pass that object to those services to test functions, it will give you additional benefit, if you want to use dummy/test DB for testing you can set that in test cases.