node.js - 为什么我的 sinon 存根表现得像在调用真正的函数?
问题描述
我正在尝试遵循以下示例:https : //www.alexjamesbrown.com/blog/development/stubbing-middleware-testing-express-supertest/ 但 sinon 存根似乎没有执行包装的代码。我看过很多关于这个问题的 stackoverflow 帖子,但没有一个答案能帮助我弄清楚我做错了什么。每当我运行测试时,都会出现以下错误:
1) should return a list of sites
0 通过 (42ms) 1 失败
- GET /api/config/buildPro/sites 应该返回一个站点列表:错误:预期 200“OK”,在 Test._assertStatus (node_modules\supertest\lib\test.js:268:12) 处得到 403“Forbidden” ._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)
这让我相信它不是调用存根代码,而是执行实际的授权函数。这是我的代码:
应用程序.js
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;
授权.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();
});
});
});
解决方案
而是执行实际授权
这正是正在发生的事情。
请注意服务器中的此代码:
app.all('/api/*', authorization.authorize);
这解决authorize
了此特定程序状态下的函数引用,并且 express 将使用此特定函数(原始函数!)用于程序的其余部分。
这个:
ensureAuthenticatedSpy = sinon.stub(authorization, 'authorize');
稍后调用,并且考虑到 sinon 无权更改对authorize
先前捕获的原始的引用......是无操作的。
IOW,基本 Javascript 应用程序中的依赖注入并不像人们想要的那么简单。
要解决方法,您可以更改原始路线app.js
:
app.all('/api/*', (req, res, next) => authorization.authorize(req, res, next));
现在,您的闭包将在authorization.authorize
每次调用时解析,从而启用您感兴趣的模拟/间谍功能。但是,这种解决方案远非优雅。
推荐阅读
- r - R:聚类算法的特殊要求
- java - 帕斯卡的三角递归 Java
- c - 在 C 中,他们无论如何都是逐行读取文件内容并将每个整数值(前行)分别存储到数组中的方式吗?
- javascript - 此选项标签中使用的技术是什么?
- mysql - 试图做不在的地方
- atom-editor - 如何在 atom 中增加终端字体大小
- android - 是否有任何选项可以在不启用计费帐户的情况下在 android 应用程序中尝试 Google Cloud Vision api 进行测试
- android - 通过 VoIP 进行音频呼叫的应用程序。
- pyspark - 如何将 PySpark 中的 DataFrame 输出保存到 TextFile?
- java - 如何在 android 中创建 gif 图像 ID 数组?