Alexander Mills Alexander Mills - 1 month ago 15
Node.js Question

Unit testing Express / Loopback middleware without starting a server

Is there a way to unit test Express / Loopback middleware without actually creating a server and listening on a port?

The problem I have is that creating multiple servers in my test code will introduce the problem of port conflicts.

Answer

You can use the supertest module.

You may pass an http.Server, or a Function to request() - if the server is not already listening for connections then it is bound to an ephemeral port for you so there is no need to keep track of ports.

Mocha

An example with mocha

var request = require('supertest');
var app = require('path/to/server.js');

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

Ava

Also, you might be interested in the ava test runner instead of mocha.

Main reason : process isolation between test files

This is usually my test file template with ava

var describe = require('ava-spec').describe;
var app = require('path/to/server.js');
var request = require('supertest');

describe("REST API", function(it){
  it.before.cb(function(t){
    request(app)
      .post('/api/Clients/')
      .send({
        "username": "foo",
        "password": "bar"
      })
      .expect(200, function(err, res){
          t.end(err);
      });
  });

  it.serial.cb('Does something',
  function(t){
    request(app)
      .get(//..)
      .expect(404, function(err, res){
        if (err) return t.end(err);
        t.end();
      });
  });
  it.serial.cb('Does something else afterward',
  function(t){
    request(app)
      .get(//..)
      .expect(401, function(err, res){
        if (err) return t.end(err);
        t.end();
      });
  });
});

The serial identifier tells ava to run the it clause serially. Otherwise it will run all tests from all files in parallel.

Thanks to process isolation, each test file gets its own, isolated loopback instance (and node environment in general), and all test files can be run in parallel, which speeds up tests as well. Inside each test file however, using serial, tests will run one after another, in the order they are written in the file.