为什么我无法使用sinon正确地对twilio库进行桩测试?

3

在我的代码中,我有:

function handleMessage() {
  const twilio = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
  let recordings = twilio.recordings(foundConference.RecordingSid);
  console.log('recordings', recordings);
  return recordings.remove();
}

在我的存根中,我有:

const sinon = require('sinon');
const twilio = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

exports.twilioRecordings = () => {
  console.log('about to stub', twilio.recordings);
  sinon.stub(twilio, 'recordings').returns('here');
  console.log('finished stub', twilio.recordings);

  return;
};

然而,它并没有真正创建一个存根函数。它仍然使用原始的recordings函数。我做错了什么?


你是如何尝试使用存根的? - philnash
在我的 handleMessage 函数中,我有这一行代码 let recordings = twilio.recordings(foundConference.RecordingSid); - Shamoon
1
我能看到,我的意思是你是如何组合测试文件来使用存根的? - philnash
1个回答

6

Twilio npm包返回一个函数,每次调用都会创建一个新对象,它不是单例。因此,您的存根化twilio实例仅限于测试。

另外,twilio.recordings(以及所有其他属性)通过原型中的getter函数定义,因此它们是只读的

Object.defineProperty(Twilio.prototype,
  'recordings', {
  get: function() {
    return this.api.account.recordings;
  }
});

所以,模拟实际的twilio实例没有效果。除非您更改实例的原型,但我认为仅进行单元测试不值得这样做。
我建议您重构代码,将twilio初始化放入单独的方法中:
function getTwilio() {
   return require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
}

接下来你的hangleMessage函数将会像这样:

function handleMessage() {
  const twilio = this.getTwilio();
  const recordings = twilio.recordings(...);
  ...
}

接下来,在您的测试中,您可以将getTwilio()存根化以返回存根:

const twilioStub = {
    recordings: sinon.stub(),
    remove: sinon.stub()
}
sinon.stub(myAwesomeModule, 'getTwilio').returns(twilioStub);

你也可以考虑使用 mock-require 包:

const sinon = require('sinon');
const mock = require('mock-require');
mock('twilio', () => ({
  recordings: sinon.stub(),
}));

这里有一个关于如何模拟依赖项的问题,可能还有其他有用的库可以存根所需的模块。

希望对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接