Next, let's test our create engine function. Like our previous createUser request handler, the src/engines/users/create/index.js module contains two import statements, which makes it difficult to test. Therefore, just like before, we must pull these dependencies out, and import them back into src/index.js:
import createUserValidator from './validators/users/create';
...
const handlerToValidatorMap = new Map([
[createUserHandler, createUserValidator],
]);
...
app.post('/users', injectHandlerDependencies(createUserHandler, client, handlerToEngineMap, handlerToValidatorMap, ValidationError));
Then, update the injectHandlerDependencies function to inject the validator function into the handler:
function injectHandlerDependencies(
handler, db, handlerToEngineMap, handlerToValidatorMap, ValidationError,
) {
const engine = handlerToEngineMap.get(handler);
const validator = handlerToValidatorMap.get(handler);
return (req, res) => { handler(req, res, db, engine, validator, ValidationError); };
}
Then, inside the handler, relay the validator function and ValidationError class into the engine function:
function createUser(req, res, db, create, validator, ValidationError) {
return create(req, db, validator, ValidationError)
...
}
Finally, update the unit tests to cater for this change. Once all tests pass, commit this change to Git:
$ git add -A && git commit -m "Implement dependency injection for engine"
Once that's committed, let's move on to writing the unit tests themselves. There are only two cases to test for – when the validator returns with a ValidationError, or when it returns with undefined. Again, because we don't want our unit tests to depend on the validator, and so we will use stubs to simulate its functionality. Attempt to implement it yourself and compare it with our implementation, as follows:
import assert from 'assert';
import { stub } from 'sinon';
import ValidationError from '../../../validators/errors/validation-error';
import create from '.';
describe('User Create Engine', function () {
let req;
let db;
let validator;
const dbIndexResult = {};
beforeEach(function () {
req = {};
db = {
index: stub().resolves(dbIndexResult),
};
});
describe('When invoked and validator returns with undefined', function () {
let promise;
beforeEach(function () {
validator = stub().returns(undefined);
promise = create(req, db, validator, ValidationError);
return promise;
});
describe('should call the validator', function () {
it('once', function () {
assert(validator.calledOnce);
});
it('with req as the only argument', function () {
assert(validator.calledWithExactly(req));
});
});
it('should relay the promise returned by db.index()', function () {
promise.then(res => assert.strictEqual(res, dbIndexResult));
});
});
describe('When validator returns with an instance of ValidationError', function () {
it('should reject with the ValidationError returned from validator', function () {
const validationError = new ValidationError();
validator = stub().returns(validationError);
return create(req, db, validator, ValidationError)
.catch(err => assert.strictEqual(err, validationError));
});
});
});
As always, run the tests and commit the code:
$ git add -A && git commit -m "Implement unit tests for Create User engine"