在回调中使用方法的Sinon加密存根

时间:2019-04-04 00:54:23

标签: javascript node.js sinon

我正在尝试测试一个简单的函数,该函数使用nodejs密码库生成一个随机名称。我正在使用sinon在pseudoRandomBytes的回调中将方法调用存根,但似乎未调用该存根。示例:

getFileName.js

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在做什么的基本理解可能是完全错误的。任何帮助将不胜感激。

2 个答案:

答案 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'),测试将失败。