如何使用Sinon Mock以this关键字定义的函数?测试报错求解
解决Mocha+Sinon测试时无法Stub
doRandomStuff的问题 你遇到的报错TypeError: Cannot stub non-existent own property doRandomStuff,核心原因是你定义doRandomStuff的方式导致Sinon无法正确识别这个属性:
在你的foo构造函数里,doRandomStuff是每个实例创建时才动态添加到this上的自有属性,而不是挂载在foo.prototype上的原型方法。这种情况下,直接Stub实例或构造函数本身的doRandomStuff都会失效,原因如下:
sinon.stub(instance,'doRandomStuff'):理论上创建实例后这个属性应该存在,但Sinon对动态添加的自有属性的检测逻辑,可能导致识别失败;sinon.stub(foo,'doRandomStuff'):你Stub的是构造函数foo本身的属性,而不是实例的属性——实例创建时会重新给this.doRandomStuff赋值,完全不受这个Stub影响。
下面提供两种可行的解决办法:
方法一:重构foo,将方法挂载到原型上(推荐)
这种方式不仅让测试更简单,也符合JS的原型链最佳实践,避免每个实例都创建重复的函数:
// 修改原foo的定义 var foo = function(){}; // 将doRandomStuff放到原型上 foo.prototype.doRandomStuff = function(callback){ // do Something callback(false); };
对应的测试代码可以这样写:
describe("Foo Test", function(){ it("testing foo", function(done){ // Stub原型上的doRandomStuff方法,指定回调参数为true const doRandomStuffStub = sinon.stub(foo.prototype, 'doRandomStuff').callsArgWith(0, true); bar(); // 验证方法是否被调用 sinon.assert.calledOnce(doRandomStuffStub); // 恢复原型方法,避免影响其他测试用例 doRandomStuffStub.restore(); done(); }); });
方法二:不修改原代码,Stubfoo构造函数返回假实例
如果不能改动原业务代码,可以通过Sinon替换foo构造函数,让它返回一个预定义好Stub方法的假实例:
describe("Foo Test", function(){ it("testing foo", function(done){ // 创建假的foo实例,包含Stub后的doRandomStuff const fakeFooInstance = { doRandomStuff: sinon.stub().callsArgWith(0, true) }; // 替换全局的foo构造函数,让它返回假实例 const fooConstructorStub = sinon.stub(window, 'foo').returns(fakeFooInstance); try { bar(); // 验证doRandomStuff是否被正确调用 sinon.assert.calledOnce(fakeFooInstance.doRandomStuff); } finally { // 必须恢复原构造函数,否则会影响其他测试 fooConstructorStub.restore(); } done(); }); });
这样当bar函数里执行new foo()时,得到的是我们的假实例,它的doRandomStuff方法会按预期调用回调并传入true,完美满足测试需求。
内容的提问来源于stack exchange,提问作者Mukesh Verma
相关产品推荐
相关产品推荐

