So far, we have been retrofitting our code with unit tests, which test each unit individually, independent of external dependencies. However, it's also important to have confidence that different units are compatible with each other. This is where integration tests are useful. So, let's add some integration tests to our User Create engine that'll test its interaction with the database.
First, let's update our npm scripts to include a test:integration script. We'll also update the glob file in our test:unit npm to be more specific and select only unit tests. Lastly, update the test script to run the integration tests after the unit tests:
"test": "yarn run test:unit && yarn run test:integration && yarn run test:e2e",
"test:unit": "mocha 'src/**/*.unit.test.js' --require @babel/register",
"test:integration": "dotenv -e envs/test.env -e envs/.env mocha -- src/**/*.integration.test.js' --require @babel/register",
The dotenv mocha part will run Mocha after loading all the environment variables. We are then using a double dash (--) to signify to our bash shell that this is the end of the options for the dotenv command; anything after the double dash is passed into the mocha command, like it did previously.
You write your integration tests in the same way as your unit tests, the only difference being instead of stubbing everything, you supply the unit you're testing with genuine parameters. Let's take a look at the signature of our create function once again:
create(req, db, createUserValidator, ValidationError)
Previously, we used stubs to simulate the real db object and createUserValidator function. For an integration test, you'd actually import the real validator function and instantiate a real Elasticsearch JavaScript client. Once again, try to implement the integration tests yourself, and check back here for our solution:
import assert from 'assert';
import elasticsearch from 'elasticsearch';
import ValidationError from '../../../validators/errors/validation-error';
import createUserValidator from '../../../validators/users/create';
import create from '.';
const db = new elasticsearch.Client({
host: `${process.env.ELASTICSEARCH_PROTOCOL}://${process.env.ELASTICSEARCH_HOSTNAME}:${process.env.ELASTICSEARCH_PORT}`,
});
describe('User Create Engine', function () {
describe('When invoked with invalid req', function () {
it('should return promise that rejects with an instance of ValidationError', function () {
const req = {};
create(req, db, createUserValidator, ValidationError)
.catch(err => assert(err instanceof ValidationError));
});
});
describe('When invoked with valid req', function () {
it('should return a success object containing the user ID', function () {
const req = {
body: {
email: 'e@ma.il',
password: 'password',
profile: {},
},
};
create(req, db, createUserValidator, ValidationError)
.then((result) => {
assert.equal(result.result, 'created');
assert.equal(typeof result._id, 'string');
});
});
});
});
Again, run all the tests to make sure they all pass, then commit these changes to the repository:
$ git add -A && git commit -m "Add integration tests for Create User engine"