如何存根未直接传递给调用函数的函数?
How do I stub a function that is not directly passed to the calling function?
我有一个 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;
当我使用包含的令牌 header 从 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 的 before
挂钩中添加 verifyToken
函数
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
的方法,这样我就可以立即 return next()
。
我的问题是,是否可以在测试期间对 AuthenticationMiddleware.verifyToken
进行普遍 存根,以便所有对 API 端点的调用都调用 存根版本?
根据这两个帖子, and ,我的存根未处于活动状态的原因是 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"
},
我有一个 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;
当我使用包含的令牌 header 从 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 的 before
挂钩中添加 verifyToken
函数
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
的方法,这样我就可以立即 return next()
。
我的问题是,是否可以在测试期间对 AuthenticationMiddleware.verifyToken
进行普遍 存根,以便所有对 API 端点的调用都调用 存根版本?
根据这两个帖子,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"
},