Sinon.js,如何只对一个方法进行一次存根?

7

我想知道在sinon.js中是否有可能只对一个方法进行一次存根操作?

例如:

sinon.stub(module, 'randomFunction', 'returnValue/function');

在我的测试中,module.randomFunction这个模块将在同一个测试中被多次调用,但我只希望存根触发一次,然后恢复它,使函数恢复正常行为。
真实代码的模拟:
myModule.putItem(item, function (err, data) {
  if (err) {
    // do stuff
    return callback();
  } else {
    // do other stuff
    return callback(null, data);
  }
});

第一次我想触发错误,其他时间我只想让它继续真正的流程。

在sinon中是否可能实现这一点?

此致,敬礼

Jimmy

编辑:我根据@Grimurd的答案发布了一个解决方案,解决了我的问题。


修改为明确指出存根在同一测试中被调用多次。 - jruts
添加了一个更加真实的例子。 - jruts
4个回答

7

是的,这是可能的。假设您正在使用mocha作为您的测试框架。

describe('some tests', function() {    
    afterEach(function() {
        sinon.restore();
    })

    it('is a test with a stub', function() {
        // This gets restored after each test.
        sinon.stub(module, 'randomFunction', 'returnValue/function');
    })
})

请查看Sinon沙盒API获取更多信息。 更新 针对您实际的问题,答案如下:
describe('some tests', function() {
    afterEach(function() {
        sinon.restore();
    })

    it('is a test with a stub', function() {
        // This gets restored after each test.
        sinon.stub(module, 'randomFunction')
            .onFirstCall().returns('foo')
            .onSecondCall().returns('bar')
            .onThirdCall().returns('foobar');
    })
})

请前往http://sinonjs.org/docs/查找stub.onCall(n)的说明。

更新2:自v5以来,sinon默认创建一个沙盒,因此无需显式地创建沙盒。请前往从v4迁移到v5的迁移指南了解更多信息。


我可能没有表达正确,但我的意思是在同一个测试中会多次调用存根。 - jruts

4

在我的看法中,实现期望的行为有一种更简单的方式。根据文档:

stub.callThrough();
当没有匹配条件的存根时,会导致包装到存根中的原始方法被调用。

因此,一个真实的示例如下:

let stub = sandbox.stub(module, 'method')
  .onSecondCall().returns('whatever');

stub.callThrough();

注意,原始方法也将在第一次调用时执行。


4

解决方案:

sandbox.stub(module, 'putItem')
  .onFirstCall().yields('ERROR')
  .onSecondCall().yields(null, item)

根据 @grimurd 的回答,我通过使用 "yields" 成功让它工作。"Yields" 会触发原始方法签名中找到的第一个回调函数。

所以,在第一次调用时,我基本上会说 callback('error'),而在第二次调用时,我会说 callback(null, item)

不过,某种程度上,我确实想知道 callback 是否比 yields 更好的方法名称 :)

感谢您的答案!


4
其他回答似乎忽略了问题的一个关键部分:“我只想让存根触发一次,然后恢复它,使函数恢复正常行为。”。以下是一种将给定方法存根化一次,然后恢复先前行为的方法:
let stub = sandbox.stub(module, 'method')
    .onFirstCall().returns(1)
    .onSecondCall().callsFake((...args) => {
        stub.restore();
        return module.method(...args);
    });

1
谢谢,这实际上是最有帮助的答案。不过我想知道,为什么没有更简单的方法来实现它。例如,在Jest中,默认情况下就会这样处理,无需在第一次调用后还原存根。 - mvlabat

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