Javascript 回调中方法的Sinon加密存根

Javascript 回调中方法的Sinon加密存根,javascript,node.js,sinon,Javascript,Node.js,Sinon,我正在尝试测试一个简单的函数,该函数使用nodejs加密库生成一个随机名称。我正在使用sinon在伪随机字节回调中剔除一个方法调用,但似乎没有调用该存根。例如: getFileName.js 测试(在摩卡咖啡中运行) 我希望上面的测试在调用createHash时抛出一次。如果我将crypto.createHash调用移到回调之外(在伪随机数调用之前),它就可以正常工作。我是个新手,所以我对sinon和nodejs的基本理解可能是完全错误的。任何帮助都将不胜感激。问题在于这是一个异步函数,所以测试

我正在尝试测试一个简单的函数,该函数使用nodejs加密库生成一个随机名称。我正在使用sinon在伪随机字节回调中剔除一个方法调用,但似乎没有调用该存根。例如:

getFileName.js 测试(在摩卡咖啡中运行) 我希望上面的测试在调用
createHash
时抛出一次。如果我将
crypto.createHash
调用移到回调之外(在伪随机数调用之前),它就可以正常工作。我是个新手,所以我对sinon和nodejs的基本理解可能是完全错误的。任何帮助都将不胜感激。

问题在于这是一个异步函数,所以测试代码的其余部分在回调之前执行。这样,存根将在函数实际使用之前恢复

为了使它正常工作,您应该更新
getFileName.js
,这样它会返回一个承诺-这样您就可以了

然后在你的测试中

// 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);
});

没有调用
createHash()
的原因是,由于异步函数,您在回调调用完成之前进行了断言

使用async/await的承诺将起作用。另一种不涉及将模块更改为使用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')
,测试将失败。

您使用的测试框架是什么?我使用的是mochait,回调中的断言确实不涉及更新他的模块,但是我强烈建议将他的代码移动到与承诺一起工作。不仅用于测试(它将生成更干净的代码),而且用于他使用模块的任何时候——否则,在不涉及spagetti的情况下进行后续调用将更加困难code@Gonzalo.-我同意。只是问题特别提到了回调。
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);
});
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();
  });
});