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([]));