У меня есть экспресс-приложение с конечными точками API, защищенными с помощью токена JWT
. У меня есть метод, который проверяет полученный токен.
// authentication.js
import jwt from 'jsonwebtoken';
import Settings from '../settings';
const AuthenticationMiddleware = {
verifyToken: (req, res, next) => {
const token = req.headers['x-access-token'];
if (!token) {
const msg = 'Include a valid token in the x-access-token header';
return res.status(422).json({
error: 'No token provided',
msg
});
}
try {
req.user = jwt.verify(token, Settings.jwtSecret);
req.token = token;
return next();
}
catch (e) {
return res.status(422).json({ error: 'Invalid token' });
}
}
};
export default AuthenticationMiddleware;
Это отлично работает, когда я вызываю конечные точки API из postman
с включенным заголовком токена.
Теперь у меня есть тест, как показано ниже. Их около 40, каждый из которых требует отправки токена с каждым запросом API.
// should is not used directly in the file but is added as a mocha requirement
import supertest from 'supertest';
import app from '../app';
const server = supertest.agent(app);
const BASE_URL = '/api/v1';
describe('/loans: Get all loans', () => {
it('should return a list of all loans', done => {
server
.get(`${BASE_URL}/loans`)
.expect(200)
.end((err, res) => {
res.status.should.equal(200);
res.body.data.should.be.an.instanceOf(Array);
for (const each of res.body.data) {
each.should.have.property('id');
each.should.have.property('userid');
}
done();
});
});
});
Я посмотрел на sinon
и попытался заглушить функцию verifyToken
в хуке before
мокко вот так
import sinon from 'sinon';
import AuthenticationMiddleware from '../middleware/authentication';
before(() => {
const stub = sinon.stub(AuthenticationMiddleware, 'verifyToken');
stub.returnsThis()
});
Но я уже вижу здесь проблему. Хотя заглушка verifyToken
может быть создана, она НЕ используется во время теста. verifyToken
, который вызывается во время теста, передается как промежуточное ПО из маршрута, например так
router.get('/loans', AuthenticationMiddleware.verifyToken, LoansController.get_all_loans);
Мне нужен способ заглушить verifyToken
во время теста, чтобы я мог просто вернуться next()
немедленно.
У меня вопрос, можно ли заглушить AuthenticationMiddleware.verifyToken
повсеместно во время теста, чтобы все обращения к конечной точке API вызывали версию заглушенный?
Согласно этим двум сообщениям, Заглушка Sinon пропускается как промежуточное ПО Node Express и Как смоделировать промежуточное ПО в Express, чтобы пропустить аутентификацию для модульного теста?, причина того, что моя заглушка не была активной, заключалась в том, что app
импортировался и кешировался еще до того, как заглушка была создана, поэтому приложение использует ту, которую оно закешировало.
Таким образом, решение состояло в том, чтобы изменить требуемую функцию до того, как приложение получит возможность ее кэшировать. Что я сделал (я наткнулся на это методом проб и ошибок), так это создал файл в моей тестовой папке с именем stubs.js
и вот его содержимое.
import sinon from 'sinon';
import AuthenticationMiddleware from '../middleware/authentication';
sinon.stub(AuthenticationMiddleware, 'verifyToken').callsFake(
(req, res, next) => next()
);
Затем мне нужен этот файл в моем тестировщике в package.json
вот так
"scripts": {
"test": "nyc --reporter=html --reporter=text --reporter=lcov mocha -r @babel/register -r should -r test/stubs.js"
},