使用 sinonjs 测试方法调用的上下文

Test the context of a method call using sinonjs

本文关键字:上下文 调用 测试方法 sinonjs 使用      更新时间:2023-09-26

>我有一个类,我在初始化时绑定了一个方法,如下所示 -

function MyClass() {
    this.onHttpCallback = _.bind(onHttpCallback, this);
}
function onHttpCallback(){
   //... 
}

如何测试调用onHttpCallback时是否总是使用 MyClass 的对象作为上下文进行调用?

我正在使用 sinon.js 来模拟,以下代码不起作用 -

it('should be binded', function () {
    //ctrl is an object of MyClass
    var dummy_obj = {};
    var spy = sinon.spy(ctrl.onHttpCallback);
    spy.call(dummy_obj);
    spy.alwaysCalledOn(ctrl).should.be.ok;
});

更新根据以下答案中的注释,似乎无法测试方法的绑定。

我对问题的看法

//Source.js
function MyClass() {
}
MyClass.prototype.init = function(){
   this.onHttpCallback = _.bind(MyClass.onHttpCallback, this);
}

MyClass.onHttpCallback(){
   //... 
}
//Test.js
it('should bind onHttpCallback', function () {
    sinon.spy(_, 'bind');
    ctrl.init();
    _.bind.calledWith(ctrl.constructor.onHttpCallback, ctrl).should.be.ok;
    _.bind.restore();
});

像魅力一样工作!

如果您

想知道为什么即使您之前明确将其绑定为MyClassthis也会更改,那是因为您在间谍上使用call dummy_obj
间谍包装原始函数,因此它没有该函数绑定的概念。它仍然会在包装函数上接受不同的绑定,然后尝试使用该this调用原始绑定,然后被原始函数忽略。

var context = {foo: 'bar'};
var original = _.bind(function () { console.log(this); }, context);
var spy = function (original) {
    var spyFn = function () {
        var _this = this;
        spyFn.calledOn = function (ctx) { return ctx === _this; };
        return original.apply(this, arguments);
    };
    return spyFn;
};
var originalSpy = spy(original);
// Will call the spyFn with a different `this`, but will not affect the original binding
originalSpy.call({something: 'else'});
>> {foo: 'bar'}
// Since the spy cannot know the original binding, it will think the assumption is false.
originalSpy.calledOn(context) === false;