为什么我的sinon存根会像调用实函数那样工作? [英] Why is my sinon stub acting like it's calling the real function?

查看:100
本文介绍了为什么我的sinon存根会像调用实函数那样工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试遵循以下示例:> ://www.alexjamesbrown.com/blog/development/stubbing-middleware-testing-express-supertest/,但sinon存根似乎没有执行包装的代码.我见过很多关于此问题的stackoverflow帖子,但没有一个答案可以帮助我弄清楚我在做什么错.每当我运行测试时,都会出现以下错误:

I'm trying to follow this example: https://www.alexjamesbrown.com/blog/development/stubbing-middleware-testing-express-supertest/ but the sinon stub doesn't seem to be executing the wrapped code. I've seen lots of stackoverflow posts regarding this issue but none of the answers have helped me figure out what I'm doing wrong. Whenever I run my test I get the following error:

1) should return a list of sites

0次通过(42ms)1次失败

0 passing (42ms) 1 failing

  1. 获取/api/config/buildPro/sites 应该返回站点列表: 错误:预期200"OK",得到403"Forbidden". 在Test._assertStatus(node_modules \ supertest \ lib \ test.js:268:12) 在Test._assertFunction(node_modules \ supertest \ lib \ test.js:283:11) 在Test.assert(node_modules \ supertest \ lib \ test.js:173:18) 在Server.localAssert(node_modules \ supertest \ lib \ test.js:131:12) 在emitCloseNT(net.js:1655:8) 在processTicksAndRejections(internal/process/task_queues.js:83:21)
  1. GET /api/config/buildPro/sites should return a list of sites: Error: expected 200 "OK", got 403 "Forbidden" at Test._assertStatus (node_modules\supertest\lib\test.js:268:12) at Test._assertFunction (node_modules\supertest\lib\test.js:283:11) at Test.assert (node_modules\supertest\lib\test.js:173:18) at Server.localAssert (node_modules\supertest\lib\test.js:131:12) at emitCloseNT (net.js:1655:8) at processTicksAndRejections (internal/process/task_queues.js:83:21)

这使我相信它不是在调用存根代码,而是执行实际的授权功能.这是我的代码:

This leads me to believe it's not calling the stub code but instead executes the actual authorization function. Here's my code:

const express = require('express');
const app = express();
const authorization = require('./security/authorization');

const configRoutes = require('./api/routes/config');

app.all('/api/*', authorization.authorize);
app.use('/api/config', configRoutes);

module.exports = app;

authorization.js

const aad = require('azure-ad-jwt');

module.exports.authorize = (req, res, next) => {
    if(!req.headers.authorization){
        res.status(403).json({
            message: "Auth failed"
        });
        return;
    }

    const jwtToken = req.headers.authorization.replace('Bearer ', '');

    aad.verify(jwtToken, null, function (err, result) {
        if (result) {
            next();
        } else {
            res.status(401).json({
                message: "Auth failed"
            });
        }
    });
};

config.spec.js

const request = require('supertest');
const sinon = require('sinon');
const app = require('../app');
const authorization = require('../security/authorization');

var agent;

describe('GET /api/names', () => {
    before(() => {
        ensureAuthenticatedSpy = sinon.stub(authorization, 'authorize');

        ensureAuthenticatedSpy.callsArgWithAsync(2);

        agent = require('supertest')
            .agent(require('../app'));
    });

    it('should return a list of names', done => {
        agent
            .get('/api/config/buildPro/sites')
            .expect(200)
            .end((err, res) => {
                if (err) return done(err);
                done();
            });
    });
});

推荐答案

执行实际授权

这正是正在发生的事情.

This is exactly what is happening.

请注意服务器中的以下代码:

Note this code in server:

app.all('/api/*', authorization.authorize);

这将在程序的特定状态下解析authorize函数引用,而express将在程序的其余部分使用此特定功能(原始功能!).

This resolves authorize function reference in this particular state of program and express will use this particular function (original one!) for rest of program.

此:

ensureAuthenticatedSpy = sinon.stub(authorization, 'authorize');

稍后被调用,并且鉴于sinon无权更改对先前捕获的原始authorize的引用...是无操作.

is called later and given that sinon has no power to change references to original authorize captured previously ... is no-op.

IOW,基本Javascript应用程序中的依赖项注入并不像人们想要的那么简单.

IOW, dependency injection in basic Javascript apps is not as simple as one might want.

要解决此问题,您可以在app.js中更改原始路线:

To workaround, you can change original route in app.js:

app.all('/api/*', (req, res, next) => authorization.authorize(req, res, next));

现在,您的闭包将在每次调用时解析authorization.authorize,从而启用您感兴趣的模拟/间谍功能.但这绝非优雅的解决方案.

Now, your closure would resolve authorization.authorize every-time it's called, enabling mocking/spying function you're interested in. However this is solution is far from elegant.

这篇关于为什么我的sinon存根会像调用实函数那样工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆