GUIDE

The road ahead will be long and our climb will be steep

Mock a Method When Test Express Api

| Comments

I think many guys are using express as they backend service framework, there is a most important thing Test. We should write test for the apis that usually contains a lot of business logics.

Today I want to show my experiences on writing test for express apis. Dependencies

"babel-register": "6.23.0",
"chai": "3.5.0",
"chai-as-promised": "6.0.0",
"mocha": "3.3.0",
"sinon": "2.2.0",
"supertest": "3.0.0"

Makefile

TESTS = src/test/**/*.spec.js
REPORTER = spec

NODE_ENV = test

tests:
  @./node_modules/.bin/mocha \
    --compilers js:babel-register \
    --require src/test/test-helper.js \
    --timeout 10000 \
    --colors \
    --reporter $(REPORTER) \
    $(TESTS)

.PHONY: tests

test-helper.js

import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';

chai.use(chaiAsPromised);
global.expect = chai.expect;

I use supertest to send a reqeust to api, here I supply one example, because it confuses me for a long time.

Example

Update roles api, it will check current user permission firstly

case 1, user have RoleUpdate permission case 2, user don’t have RoleUpdate permission

router.route('/:id/roles').put(hasPermission('RoleUpdate'), (req, res, next) => {
  ...
});

export let hasPermission = (name) => {
  return (req, res, next) => {
    readPermission(req.currentUser)
      .then(results => {
        let permissions = results.map(result => result.name);
        if (permissions.indexOf(name) === -1) {
          return next(new PermissionError(`Sorry, You don't have ${name} permission`));
        }
        next();
      })
      .catch(err => next(err));
  }
};

let readPermission = (username) => {
  return Permisison.findByUser(username);
};

In these two case, the directly thought is mock the hasPermission or export readPermission then mock him, but unfortunately, all of these solutions fail. Because it runs before the app starts.

If we mock Permisison.findByUser, it can works well.

let sandbox = sinon.sandbox.create();

case 1
sandbox.stub(Permisison, 'findByUser').returns(RSVP.resolve([{ name: 'RoleUpdate' }]));
...
case 2
sandbox.stub(Permisison, 'findByUser').returns(RSVP.resolve([]));

Comments