Как заглушить функцию, которая не передается напрямую вызывающей функции? - PullRequest
0 голосов
/ 30 мая 2019

У меня есть экспресс-приложение с конечными точками 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 вызывали версию stubbed ?

1 Ответ

0 голосов
/ 30 мая 2019

Согласно этим двум постам, Заглушка Sinon пропускается как промежуточное программное обеспечение узла 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"
    },
...