我正在尝试使用nodejs加密库测试一个生成随机名称的简单函数。我正在使用sinon在pseudoRandomBytes的回调中存根方法调用,但是似乎没有调用存根。例:
const crypto = require('crypto');
module.exports = (req, file, cb) => {
crypto.pseudoRandomBytes(32, (err, raw) => {
try{
cb(err, err ? undefined : crypto.createHash('MD5').update(raw).digest('hex'));
} catch(err) {
cb(err);
}
});
};
it('Crypto Error: createHash', function () {
const crypto = require('crypto');
const expectedError = new Error('stub error occurred');
let cryptoStub = sinon.stub(crypto, 'createHash').throws(expectedError);
let callback = sinon.spy();
getFileName(null, null, callback);
cryptoStub.restore();
sinon.assert.calledWith(callback, expectedError);
});
我希望上面的测试在createHash
被调用时抛出。如果我在回调之外(在pseudoRandomNumber调用之前)移动crypto.createHash
调用,它就可以正常工作。我有点新手所以我对sinon和nodejs所做的基本理解可能是完全错误的。任何帮助将非常感激。
看起来createHash()
似乎没有被调用的原因是因为你在回调调用完成之前由于异步函数而做出断言。
使用async / await的promise可以正常工作。另一种不涉及更改模块以使用promise的方法是在回调中执行断言。
it('Crypto Error: createHash', function (done) {
const crypto = require('crypto');
const expectedError = new Error('stub error occurred');
let cryptoStub = sinon.stub(crypto, 'createHash').throws(expectedError);
getFileName(null, null, function (err, hash) {
sinon.assert.match(err, expectedError);
cryptoStub.restore();
done();
});
});
这样,您可以检查是否使用预期错误调用了回调。确认这一点的一种方法是你可以将第4行更改为.throws('some other error')
,测试将失败。
问题是crypto.pseudoRandomBytes()是一个异步函数,所以你的测试代码的其余部分在你的回调之前执行。这样,您的存根就会在您的功能实际使用之前恢复。
为了使它正常工作,你应该更新你的getFileName.js
,以便它返回一个承诺 - 这样你就可以await it
module.exports = (req, file, cb) => {
return new Promise((resolve, reject) => {
crypto.pseudoRandomBytes(32, (err, raw) => {
try{
cb(err, err ? undefined : crypto.createHash('MD5').update(raw).digest('hex'));
resolve();
} catch(err) {
reject(cb(err));
}
});
});
};
然后在你的测试中
// added async
it('Crypto Error: createHash', async () => {
const crypto = require('crypto');
const expectedError = new Error('stub error occurred');
let cryptoStub = sinon.stub(crypto, 'createHash').throws(expectedError);
let callback = sinon.spy();
await getFileName(null, null, callback);
// once we are here, the callback has already been executed and the promise that getFileName resolved.
cryptoStub.restore();
sinon.assert.calledWith(callback, expectedError);
});