我正在尝试测试一个简单的函数,该函数使用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
就会引发上述测试。如果将crypto.createHash
调用移到回调之外(在pseudoRandomNumber调用之前),则可以正常工作。我有点新手,所以我对sinon和nodejs在做什么的基本理解可能是完全错误的。任何帮助将不胜感激。
答案 0 :(得分:1)
问题在于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);
});
答案 1 :(得分:1)
之所以没有调用createHash()
的原因是因为您由于异步功能而在回调调用完成之前进行了断言。
使用异步/等待的承诺将起作用。另一种不涉及将模块更改为使用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')
,测试将失败。