How should I start my nodejs application automatically for tests

Problem

I have a nodejs restful style service which has no front end, it just accepts data and then does something with it.

I have unit tested most of the method level stuff I want to, however now I want to basically do some automated tests to prove it all works together. When I am using ASP.MVC and IIS its easy as the server is always on, so I just setup the scenario (insert dummy guff into DB) then make a HttpRequest and send it to the server and assert that I get back what I expect.

However there are a few challenges in nodejs as the applications need to be run via command line or some other mechanism, so given that I have an app.js which will start listening, is there some way for me to automatically start that going before I run my tests and then close it once my tests are finished?

I am currently using Yadda with Mocha for my testing so I can keep it written in a BDD style way, however I am hoping the starting of the web app is agnostic of the frameworks I am using.

Problem courtesy of: Grofit

Solution

Just expose some methods to start and stop your webserver. Your app.js file could be something like this:

var app = express()
var server = null
var port = 3000

// configure your app here...

exports.start = function(cb) {
  server = http.createServer(app).listen(port, function () {
    console.log('Express server listening on port ' + port)

    cb && cb()
  })
}

exports.close = function(cb) {
  if (server) server.close(cb)
}

// when app.js is launched directly
if (module.id === require.main.id) {
  exports.start()
}

And then in your tests you can do something like this (mocha based example):

var app = require('../app')

before(function(done) {
  app.start(done)
})

after(function(done) {
  app.close(done)
})
Solution courtesy of: gimenete

Discussion

Have a look to supertest https://github.com/visionmedia/supertest You can write test like

describe('GET /users', function(){
 it('respond with json', function(done){
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);   
  }) 
 })
Discussion courtesy of: alfonsodev

This recipe can be found in it's original form on Stack Over Flow.