PhantomJS/Sinon环境下如何正确Stub Promise解决.done调用报错问题
问题原因解析
a) 报错根因
你当前对SERVICE_ACCESSOR.makeCall的Stub仅返回了空对象{},但业务代码中会链式调用该方法返回值的.done()和.fail()方法,空对象不存在这两个方法,因此触发类型错误。报错中出现的callService应为代码笔误,实际对应业务逻辑中的makeCall方法,问题本质一致。
b) 未定义对象说明
报错中提到的未定义对象是.done方法。SERVICE_ACCESSOR.makeCall(params)返回空对象后,访问空对象的done属性得到undefined,将undefined作为函数调用就会抛出该错误。
正确Stub/Mock实现方案
你需要让makeCall的返回值模拟jQuery Deferred Promise的接口,提供.done、.fail方法,同时主动触发回调才能让unlock方法被调用,通过测试断言。另外你原有的LOCKER mock存在参数传递缺失的问题,也需要同步修正,修改后的setup代码如下:
var setup = function() { P.mock('service-accessor', function () { return { makeCall: sinon.stub().returns({ done: function(successCallback) { // 模拟请求成功,触发成功回调,可自定义传入测试用的返回数据 successCallback({code: 0, msg: "success"}); // 返回自身支持链式调用,保证后续.fail方法可以正常执行 return this; }, fail: function(failCallback) { // 若需要测试失败场景,可在这里主动触发fail回调 return this; } }) }; }); P.mock('locker', function () { var methods = { execute: function (lockId, wrapped) { console.log('locked - ' + lockId) // 原逻辑未传递unlock参数,会导致业务代码中的unlock为undefined,此处补充传入 wrapped(methods.unlock) }, unlock: sinon.stub() }; return { execute: methods.execute, unlock: methods.unlock }; }); P.start(); }
上述修改完成后即可跑通成功路径的测试,若需要测试失败场景,只需调换回调触发逻辑,在.fail中触发回调、.done中仅返回自身即可。
内容的提问来源于stack exchange,提问作者Mylies
相关产品推荐
相关产品推荐

