integration testing an api with mocha and superagent
This seemed to be the week people showed me testing triangles.
If you’ve never seen one then I’ve included one below.
![](/assets/images/uploads/2017/01/Group-5.png)
This doesn’t give you the full range of tests but it does give you an overview.
The top of the triangle can includes acceptance tests, performance tests and security - anything that sits over the whole system.
The example I have used here is against a simple API, but tools like superagent could also run against the front-end of a website.
API
I’ve built a small API in express, this has a couple of routes that serve user data.
- /api/users - this gives a list of users
- /api/users/:id - this gives a 404 error if not found, or the requested user
These are self-contained integration tests, before all the tests a script starts a server.
Most of the time I’d be using a CI tool like Jenkins to run these tests against an actual service. Rather than having a static data file, this might be running against either a stub or database.
For these tests I’ve Mocha as a test runner and chai as an assertion library.
To drive requests to the website I have used superagent this can work both server and client side.
I did look at chai-http this mostly wraps superagent, so didn’t seem to add value.
Tests
With this api example there will be three tests
- test to get all users
- test to get user with valid id
- test to get user with invalid id
const {assert} = require('chai');
const superagent = require('superagent');
const status = require('http-status');
// include server
const server = require('../index');
// ser variables
const port = process.env.PORT || 3000;
const validUserID = 'A0001';
const invalidUserID = 'B0001';
describe('/api/users', function() {
let app;
before(function() {
// start server
app = server(port);
});
after(function() {
// close server
app.close();
});
it('should return list of users when called', function(done) {
superagent
.get(`http://localhost:${port}/api/users`)
.end(function(err, res) {
assert.ifError(err);
assert.equal(res.status, status.OK);
const result = JSON.parse(res.text);
assert.lengthOf(result, 3);
done();
});
});
describe('/:id', function() {
it('returns user when valid user id is used', function(done) {
superagent
.get(`http://localhost:${port}/api/users/${validUserID}`)
.end(function(err, res) {
assert.ifError(err);
assert.equal(res.status, status.OK);
const result = JSON.parse(res.text);
assert.equal(result.id, validUserID);
done();
});
});
it('returns 404 error with message when user does not exist', function(done) {
superagent
.get(`http://localhost:${port}/api/users/${invalidUserID}`)
.end(function(err, res) {
assert.equal(res.status, status.NOT_FOUND);
const result = JSON.parse(res.text);
assert.equal(result.message, `User ${invalidUserID} was not found.`);
done();
});
});
});
});
This will start up a server then run the tests against it, this could also be run on an external website, or against a HTML front-end.
The output of the tests are below.
/api/users
✓ should return list of users when called
/:id
✓ returns user when valid user id is used
✓ returns 404 error with message when user does not exist
3 passing (109ms)