如何使用 sinon 和 stubbing (nodeJS) 测试包含大量逻辑的路由器代码
How to test router code that contains heavy logic using sinon and stubbing (nodeJS)
我刚开始使用 sinon,如果我的问题很奇怪,我很抱歉,我到处都找了,但找不到解决办法。
我有带 Express 路由器的应用程序。我想为其中一条路线编写 uint 测试。该路由有一个内部函数 'heavy',这意味着它与 promise 异步,实际上调用外部 api。我想在测试中存根该内部函数,这样它就不会使用 api,并且 return 我自己的数据而不是原始方法。
这是目前的代码:
routes/setOrder.js:
// the inner function I want to stub
var verifyPayment = function(saleId) {
return new Promise((resolve, reject) => {
logger.info(`verifyPayment: ${saleId}`);
externalAPICall.get( // <==this is the 'heavey part!!
saleId,
function (error, sale) {
if(error) {
return reject(`Error querying sale(${saleId}): ${error}`);
}
resolve(sale);
});
});
}
router.get('/paymentId/:paymentId', setOrderWithGet);
const setOrderWithGet =async function(req, res, next) {
const { paymentId } = req.params;
verifyPayment(paymentId)
.then(async sale => {
try {
console.log(`sale:${sale}`);
res.send(JSON.stringify({"status": "ok!" }));
} catch (err) {
logger.warn(err)
res.send(JSON.stringify({"status": "fail.."}));
}
})
.catch(reason => {
logger.warn(`[] Payment(${paymentId}) is not valid ${reason}`);
res.send(JSON.stringify({"status": "fail.."}));
});
}
module.exports = router;
module.exports.setOrderWithGet = setOrderWithGet;
module.exports.verifyPayment = verifyPayment;
setOrderTest.js:
const setOrderStub = require('../routes/setOrder');
describe("POST /setOrder", () => {
beforeEach(() => {
sinon.stub(setOrderStub, 'verifyPayment').resolves({....});
});
afterEach(() => {
sinon.restore();
});
describe("test1", () => {
it("setOrder first attempt", () => {
let req ={params : {'paymentId' : 'mypamentid1'}};
setOrderStub.setOrderWithGet(req,{});
});
});
});
这一行:
sinon.stub(setOrderStub, 'verifyPayment').resolves({....});
...在 setOrder
模块的 模块导出 上存根 verifyPayment
函数。
现在 setOrderWithGet
直接调用 verifyPayment
函数,因此它不受 模块导出 .
任何更改的影响
将 setOrderWithGet
更改为使用 模块导出 调用 verifyPayment
:
const setOrderWithGet = async function(req, res, next) {
// ...
module.exports.verifyPayment(paymentId) // <= call the module export for verifyPayment
// ...
}
...您的存根将被调用。
我刚开始使用 sinon,如果我的问题很奇怪,我很抱歉,我到处都找了,但找不到解决办法。
我有带 Express 路由器的应用程序。我想为其中一条路线编写 uint 测试。该路由有一个内部函数 'heavy',这意味着它与 promise 异步,实际上调用外部 api。我想在测试中存根该内部函数,这样它就不会使用 api,并且 return 我自己的数据而不是原始方法。
这是目前的代码:
routes/setOrder.js:
// the inner function I want to stub
var verifyPayment = function(saleId) {
return new Promise((resolve, reject) => {
logger.info(`verifyPayment: ${saleId}`);
externalAPICall.get( // <==this is the 'heavey part!!
saleId,
function (error, sale) {
if(error) {
return reject(`Error querying sale(${saleId}): ${error}`);
}
resolve(sale);
});
});
}
router.get('/paymentId/:paymentId', setOrderWithGet);
const setOrderWithGet =async function(req, res, next) {
const { paymentId } = req.params;
verifyPayment(paymentId)
.then(async sale => {
try {
console.log(`sale:${sale}`);
res.send(JSON.stringify({"status": "ok!" }));
} catch (err) {
logger.warn(err)
res.send(JSON.stringify({"status": "fail.."}));
}
})
.catch(reason => {
logger.warn(`[] Payment(${paymentId}) is not valid ${reason}`);
res.send(JSON.stringify({"status": "fail.."}));
});
}
module.exports = router;
module.exports.setOrderWithGet = setOrderWithGet;
module.exports.verifyPayment = verifyPayment;
setOrderTest.js:
const setOrderStub = require('../routes/setOrder');
describe("POST /setOrder", () => {
beforeEach(() => {
sinon.stub(setOrderStub, 'verifyPayment').resolves({....});
});
afterEach(() => {
sinon.restore();
});
describe("test1", () => {
it("setOrder first attempt", () => {
let req ={params : {'paymentId' : 'mypamentid1'}};
setOrderStub.setOrderWithGet(req,{});
});
});
});
这一行:
sinon.stub(setOrderStub, 'verifyPayment').resolves({....});
...在 setOrder
模块的 模块导出 上存根 verifyPayment
函数。
现在 setOrderWithGet
直接调用 verifyPayment
函数,因此它不受 模块导出 .
将 setOrderWithGet
更改为使用 模块导出 调用 verifyPayment
:
const setOrderWithGet = async function(req, res, next) {
// ...
module.exports.verifyPayment(paymentId) // <= call the module export for verifyPayment
// ...
}
...您的存根将被调用。