我如何在 Sinon 中存入一系列方法?
How do I stub a chain of methods in Sinon?
我知道如何用存根替换一个函数。
sandbox.stub(Cars, "findOne",
() => {return car1 });
但是现在我的函数中有一行我想测试我需要存根看起来像这样
Cars.find().fetch()
所以这里有一个功能链,我不确定我需要做什么。我如何将 "find" 存根到 return 可以用来存根 "fetch" 的东西?
试试这个:
sandbox.stub(Cars, "find", () => {
return {
fetch: sinon.stub().returns(anything);
};
});
这是另一种方法,它也允许监视 jQuery 方法链——我花了很长时间才弄明白。
在这个例子中,我试图测试一个电子邮件字段是否被清除
//set up stub and spy
const valSpy = sandbox.spy();
const jQueryStub = sandbox
.stub($.prototype, "find") // this prototype is important
.withArgs("input[name=email]")
.returns({ val: valSpy });
// call function under test
learnerAlreadyAccepted(inviteDoc);
// check expectations
expect(jQueryStub).to.have.been.called; // not really necessary
expect(valSpy).to.have.been.calledWith("");
被测函数(大致):
learnerAlreadyAccepted = function(doc) {
$("form").find("input[name=email]").val("");
}
此处显示的将函数附加到存根的形式:
sandbox.stub(Cars, "find", () => {
return {
fetch: sinon.stub().returns(anything);
};
});
已弃用。
现在,截至 version 6.3
sandbox.stub(Cars, "find").callsFake(() => {
return {
fetch: sinon.stub().returns(anything);
};
});
恕我直言,我们可以使用 returns
来做到这一点。我们不需要使用 callsFake
或将其模拟为函数。
// Cars.find().fetch()
sinon.stub(Cars, 'find').returns({
fetch: sinon.stub().returns(anything)
});
如果在fetch()之后还有其他方法,我们可以使用returnsThis()
// Cars.find().fetch().where()
sinon.stub(Cars, 'find').returns({
fetch: sinon.stub().returnsThis(),
where: sinon.stub().returns(anything)
});
参考:
https://sinonjs.org/releases/v6.3.3/
希望对您有所帮助
我 运行 解决了这个问题,虽然我喜欢单个测试的解决方案,但我想要一些更动态的东西,允许跨测试重用。我也更喜欢沙盒方法,因为它使大型套件的恢复变得更加容易。最终结果:
export function setupChainedMethodStub(sandbox: sinon.SinonSandbox, obj: any, methodName: string, methodChain: string[], value: any) {
return sandbox.stub(obj, methodName).returns(generateReturns(sandbox, methodChain, value));
}
function generateReturns(sandbox: sinon.SinonSandbox, methodChain: string[], value: any): any {
if (methodChain.length === 1) {
return {
[methodChain[0]]: sandbox.stub().returns(value),
};
} else {
return {
[methodChain[0]]: sandbox.stub().returns(generateReturns(sandbox, methodChain.slice(1), value)),
};
}
}
无论我想在何处动态设置存根,我都会传入创建的沙箱和其他参数:
setupChainedMethodStub(sandbox, MyMongooseModel, 'findOne', ['sort', 'exec'], { foo: 'bar' })
然后我只有一个 sandbox.restore()
在我的最高范围 afterEach()
我有一个简单的解决方案,希望对其他人有用。
假设 fetch
也是 Cars
上的一个方法,并且 fetch
和 find
支持方法链接,Cars
可能看起来像这样:
class Cars {
fetch() {
// do stuff
return this;
}
find() {
// do stuff
return this;
}
}
[ANSWER] 我们应该能够像这样使用存根支持方法链接:
sandbox.stub(Cars, 'fetch').callsFake(function () { return this; }); // optional
sandbox.stub(Cars, 'findOne').callsFake(function () { return this; });
与 v2.0 相比有一些变化。
其中之一是:
stub(obj, 'meth', fn) has been removed, see documentation
你可以降级,但我不推荐它,相反你可以这样做:
let stub = sinon.stub(obj, "meth").callsFake(() => {
return {
meth2: sinon.stub().callsFake(() => {
return {
meth3: sinon.stub().returns(yourFixture),
};
}),
};
});
我知道如何用存根替换一个函数。
sandbox.stub(Cars, "findOne",
() => {return car1 });
但是现在我的函数中有一行我想测试我需要存根看起来像这样
Cars.find().fetch()
所以这里有一个功能链,我不确定我需要做什么。我如何将 "find" 存根到 return 可以用来存根 "fetch" 的东西?
试试这个:
sandbox.stub(Cars, "find", () => {
return {
fetch: sinon.stub().returns(anything);
};
});
这是另一种方法,它也允许监视 jQuery 方法链——我花了很长时间才弄明白。
在这个例子中,我试图测试一个电子邮件字段是否被清除
//set up stub and spy
const valSpy = sandbox.spy();
const jQueryStub = sandbox
.stub($.prototype, "find") // this prototype is important
.withArgs("input[name=email]")
.returns({ val: valSpy });
// call function under test
learnerAlreadyAccepted(inviteDoc);
// check expectations
expect(jQueryStub).to.have.been.called; // not really necessary
expect(valSpy).to.have.been.calledWith("");
被测函数(大致):
learnerAlreadyAccepted = function(doc) {
$("form").find("input[name=email]").val("");
}
此处显示的将函数附加到存根的形式:
sandbox.stub(Cars, "find", () => {
return {
fetch: sinon.stub().returns(anything);
};
});
已弃用。
现在,截至 version 6.3
sandbox.stub(Cars, "find").callsFake(() => {
return {
fetch: sinon.stub().returns(anything);
};
});
恕我直言,我们可以使用 returns
来做到这一点。我们不需要使用 callsFake
或将其模拟为函数。
// Cars.find().fetch()
sinon.stub(Cars, 'find').returns({
fetch: sinon.stub().returns(anything)
});
如果在fetch()之后还有其他方法,我们可以使用returnsThis()
// Cars.find().fetch().where()
sinon.stub(Cars, 'find').returns({
fetch: sinon.stub().returnsThis(),
where: sinon.stub().returns(anything)
});
参考: https://sinonjs.org/releases/v6.3.3/
希望对您有所帮助
我 运行 解决了这个问题,虽然我喜欢单个测试的解决方案,但我想要一些更动态的东西,允许跨测试重用。我也更喜欢沙盒方法,因为它使大型套件的恢复变得更加容易。最终结果:
export function setupChainedMethodStub(sandbox: sinon.SinonSandbox, obj: any, methodName: string, methodChain: string[], value: any) {
return sandbox.stub(obj, methodName).returns(generateReturns(sandbox, methodChain, value));
}
function generateReturns(sandbox: sinon.SinonSandbox, methodChain: string[], value: any): any {
if (methodChain.length === 1) {
return {
[methodChain[0]]: sandbox.stub().returns(value),
};
} else {
return {
[methodChain[0]]: sandbox.stub().returns(generateReturns(sandbox, methodChain.slice(1), value)),
};
}
}
无论我想在何处动态设置存根,我都会传入创建的沙箱和其他参数:
setupChainedMethodStub(sandbox, MyMongooseModel, 'findOne', ['sort', 'exec'], { foo: 'bar' })
然后我只有一个 sandbox.restore()
在我的最高范围 afterEach()
我有一个简单的解决方案,希望对其他人有用。
假设 fetch
也是 Cars
上的一个方法,并且 fetch
和 find
支持方法链接,Cars
可能看起来像这样:
class Cars {
fetch() {
// do stuff
return this;
}
find() {
// do stuff
return this;
}
}
[ANSWER] 我们应该能够像这样使用存根支持方法链接:
sandbox.stub(Cars, 'fetch').callsFake(function () { return this; }); // optional
sandbox.stub(Cars, 'findOne').callsFake(function () { return this; });
与 v2.0 相比有一些变化。
其中之一是:
stub(obj, 'meth', fn) has been removed, see documentation
你可以降级,但我不推荐它,相反你可以这样做:
let stub = sinon.stub(obj, "meth").callsFake(() => {
return {
meth2: sinon.stub().callsFake(() => {
return {
meth3: sinon.stub().returns(yourFixture),
};
}),
};
});