javascript - 如何 stub 未直接传递给调用函数的函数?

标签 javascript testing mocha.js sinon stub

我有一个 express 应用,其 API 端点使用 JWT token 进行保护。我有一个方法可以验证收到的 token 。

// 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;

当我从包含 token header 的 postman 调用 API 端点时,这工作正常。

现在我有一个如下所示的测试。大约有 40 个,每个 API 请求都需要发送 token 。

// 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 的 before Hook 中添加 verifyToken 函数

import sinon from 'sinon';
import AuthenticationMiddleware from '../middleware/authentication';

before(() => {
    const stub = sinon.stub(AuthenticationMiddleware, 'verifyToken');
    stub.returnsThis()
});

但是我已经可以看出这里有问题了。虽然可能已创建 verifyToken stub ,但在测试期间未使用它。测试期间调用的 verifyToken 像这样作为中间件从路由中传递

router.get('/loans', AuthenticationMiddleware.verifyToken, LoansController.get_all_loans);

我想要一种在测试期间 stub verifyToken 的方法,这样我就可以立即返回 next()

我的问题是,是否可以在测试期间对 AuthenticationMiddleware.verifyToken universally stub ,以便所有对 API 端点的调用都调用 stubbed> 版本?

最佳答案

根据这两个帖子,Sinon stub being skipped as node express middlewareHow to mock middleware in Express to skip authentication for unit test? ,我的 stub 未处于事件状态的原因是 app 在创建 stub 之前就已被导入和缓存,因此该应用使用它已缓存的那个。

因此解决方案是在应用有机会缓存​​它之前更改所需的功能。我所做的是(我通过反复试验偶然发现了它)是在我的测试文件夹中创建一个名为 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"
    },

关于javascript - 如何 stub 未直接传递给调用函数的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56369825/

相关文章:

javascript - Hapijs 提供 Base64 图像

testing - 如何在 elixir 中为 escript 项目编写 ExUnit 测试用例

javascript - 将元素动态添加到 SVG,元素添加到 HTML DOM 但未呈现

ruby-on-rails - RSpec 测试 `rand` 内部 `rand`

testing - BDD 可以完成 "after"吗?

javascript - 如何在 NodeJS 单元测试中模拟用户输入?

node.js - 如何在有 promise 的测试工厂中使用 spy ?

javascript - Mocha 测试和 Three.js;三未定义

javascript - 事件流 JavaScript 阅读器如何触发页面刷新?

javascript - 图表交互指南默认为光标另一侧的最远值