如何存根未直接传递给调用函数的函数?

时间:2019-05-29 23:36:00

标签: javascript testing mocha sinon stub

我有一个Express应用,其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;

当我从postman调用包含令牌头的API端点时,此方法工作正常。

现在,我进行了如下所示的测试。其中大约有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,并尝试像这样在Mocha的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进行普遍的存根(strong),以便对API端点的所有调用都称为 stubbed 版本? >

1 个答案:

答案 0 :(得分:0)

根据Sinon stub being skipped as node express middlewareHow to mock middleware in Express to skip authentication for unit test?这两个帖子,我的存根未处于活动状态的原因是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"
    },