2

The way to start locomotive.js 0.3.x no longer works in 0.4.x, as the signature of app.boot is different. I have:

before(function(done) {
  var self = this;
  var lcm = new locomotive.Locomotive();
  lcm.boot('test', function() {
    self.app = lcm.express;
    self.app.listen(4000, done);
  });
});

It throws "Error: connect ECONNREFUSED" when I tried to connect with supertest:

  request(this.app)
    .post('problems/' + problemId + '/solution_ratings')
    .set('Content-Type', 'application/json')
    .send({access_token: playerId, solution_group_id: 1, rate: 4})
    .expect(200, done);

What is the proper way to start a locomotive server for functional testing?

[Update] I have to start the server in the same process as the test in order to use sinon.js to stub/spy calls to models.

Community
  • 1
  • 1
Zebra Propulsion Lab
  • 1,736
  • 1
  • 17
  • 28

1 Answers1

-1

I've answered this on Locomotive's github for an issue, however I wanted to share here to get some feedback, as in better ways, cleaner, or any other input you might have.

I require multiple servers in an OAuth2 environment (auth, resource, dashboard..) of which mostly are Locomotive framework based.

I like functional tests since they best represent OAuth2 based authentication as opposed to only focusing my tests on a resource service where the authentication token might not best represent the user.

Here is the setup I've come up with for starting up the locomotive servers:

For your tests, say like in test/util.severs.js

var fork = require('child_process').fork,
    async = require("async");

var authApp;
var serverStatus = [];

var start = function(done) {

    authApp = fork( __dirname + '/../../authorization/server.js');
    serverStatus.push(function(callback){
        authApp.on('message', function(m){
            //console.log('[AUTHORIZATION] SENT MESSAGE: ', m);
            if (m.status == 'listening') return callback();
        });
    });

   // add others servers if you swing that way!

   async.parallel(serverStatus, function(){
         done();
   });
}
var stop = function(done) {
    authApp.kill();
    done();
}
module.exports = {
  start: start,
  stop: stop
};

Note that I'm using async here since I'm working with multiple servers (Environment is in OAuth2 which requires many servers to startup (IE resource, dashboard...)), ignore async if all you'll ever have is one server.

require the above file in your Mocha tests and do

servers = require('./util/servers');
...
before(servers.start);

  // tests away!!!

after(servers.stop);

Then in each of my locomotive-project/server.js I do the following...

// if being started as a parent process, send() won't exist, simply define
//   it as console.log or what ever other thing you do with logging stuff.
if (process.send === undefined){
  process.send = function(msg){
    console.log("status: ", msg.status);
  };
}
process.send({status: 'starting'});
...
app.boot(function(err) {
  if (err) {
    process.send({status: 'error', message: err});
    return process.exit(-1);
  } else {
    // notify any parents (fork()) that we are ready to start processing requests
    process.send({status: 'listening'});
  }
});

Using Locomotive 0.4.x here, could be different based on your version.

Is this the best way to go? Ideally I would like to move this over to Grunt, that is test server initialization (which is quite hefty as we build lots of data into the test DB), and then functional tests could run. So wondering if anyone has delved into grunt to do this instead of a before() task in Mocha.

Andrew Lank
  • 1,607
  • 1
  • 15
  • 29
  • `app.boot` doesn't seem to start the server, assuming `app` is created by `new locomotive.Locomotive()` – Zebra Propulsion Lab Apr 30 '14 at 22:43
  • yes, it's created that way, perhaps you can show some code, I am exporting it at the end: ```exports = module.exports = app;``` but this was from a previous test attempt... let me check if it's still required. – Andrew Lank Apr 30 '14 at 22:50
  • Nope, you don't need the export in your loco-proj/server.js, so I'm a little confused by your comment, are you saying it doesn't work, or you aren't sure that app.boot() does the startup. Just curious because I'd like to know more myself. – Andrew Lank Apr 30 '14 at 23:00