带 Args 的 sinon 存根可以匹配某些参数但不能匹配所有参数

我有一个函数,它是用多个参数调用的。我要检查 只是第一次争吵。其余的都是回调函数,所以我想让它们单独存在。因此,我可以使用 ajax 作为示例进行以下两个调用:

method.get = sinon.stub();
method.get(25,function(){/* success callback */},function(){/* error callback */});
method.get(10,function(){/* success callback */},function(){/* error callback */});

我不能使用 method.get.calls...,因为它不能区分第一个 get(25)和第二个 get(10)。但是如果我使用 method.get.withArgs(25).calls...,那么它也不匹配,因为 withArgs()匹配 所有参数,这是不匹配的(而且永远不可能匹配,像这样的回调)。

如何让 sinon 存根根据第一个参数检查和设置响应?

57201 次浏览

Https://sinonjs.org/releases/latest/matchers/#sinonmatchany

您可以使用 sinon.match. any:

method.get.withArgs(25, sinon.match.any, sinon.match.any);

如果只想检查第一个参数,可以使用

method.get.withArgs(25).calledOnce

或者

method.get.calledWith(25)

如果您只想检查多个参数中的一个,那么该方法对于间谍非常有效

it('should check only first argument', function ():void {
myFunction('foo', 'bar', baz');
expect(myFunctionSpy.firstCall.args[0]).to.equal('foo');
});

但是我不明白你为什么要在这里使用存根。如果你只是想检查函数是如何调用的,你应该使用一个间谍。如果你想检查它是如何调用和改变它的行为的(例如: 阻塞 ajax 调用) ,那么你应该使用一个 mock。

Sinon 的模仿者有他们自己的检查方法。对于您的情况,我知道的唯一方法是使用 sinon.match. many 来处理您不想检查的参数:

it('should check only first argument', async function (): Promise<void> {
mock.expects('myFunction').withExactArgs('foo', sinon.match.any, sinon.match.any).returns('foo');
await myFunction('foo', 'bar', baz');
mock.verify();
});

Valid()将继续进行测试,并为其他测试重置 mock,以防使用间谍或存根,您应该在每次测试后手动使用恢复()或重置()执行此操作

这里的 TypeScript 语法很抱歉: p

解决方案

withArgs 可以用于匹配一些但不是所有的参数。

具体来说,method.get.withArgs(25) 威尔检查 只是第一次争吵


纠正一下

这是不正确的:

withArgs()匹配 所有参数


细节

当调用 withArgs时,它记住传递给 给你的参数为 matchingArguments

然后当 stub被调用时,它会得到所有匹配的赝品 给你

调用 matchingFakes 时没有第二个参数,因此它返回所有具有 matchingArguments 匹配从索引0开始直到 ABC1的长度传递给 stub的参数的赝品。这意味着当假值的 matchingArguments与传递给 即使还有其他的争论的参数的开头匹配时,假值将匹配。

任何匹配的赝品都是 matchingArguments.length排序,匹配最多参数的是 调用


下面的测试证实了这种行为,并且通过了7年前的 sinon版本 1.1.0、问到这个问题时的 1.14.0和当前的 6.3.5:

import * as sinon from 'sinon';


test('withArgs', () => {


const stub = sinon.stub();


stub.withArgs(25).returns('first arg is 25!');
stub.returns('default response');


expect(stub(25)).toBe('first arg is 25!');  // SUCCESS
expect(stub(25, function () { }, function () { })).toBe('first arg is 25!');  // SUCCESS
expect(stub(10, function () { }, function () { })).toBe('default response');  // SUCCESS


});