Javascript Sinon监视继承函数

Javascript Sinon监视继承函数,javascript,sinon,Javascript,Sinon,如何使用sinon监视继承的函数 如果我有- class Parent{ constructor(){} foo(){ //do foo } } class Child extend Parent{ constructor(){ super(); } } const childSpy = sinon.spy(Child.pro

如何使用sinon监视继承的函数

如果我有-

    class Parent{
        constructor(){}
        foo(){
            //do foo
        }
    }

    class Child extend Parent{
        constructor(){
            super();
        }
    }

    const childSpy = sinon.spy(Child.prototype, 'foo')
    const parentSpy = sinon.spy(Parent.prototype, 'foo')


    new Child().foo();

    expect(childSpy).to.have.been.called; //false
    expect(parentSpy).to.have.been.called; //true
我做错了什么


上面的示例是我代码的简化版本,在实际代码中,我无法访问
子类
父类
类的实例

您最好尝试监视具体对象,而不要访问类
e、 g.

const expect = require('chai').expect;
const sinon = require('sinon');


describe('Some', () => {
  it('one', () => {
    class Parent {
      constructor() { }
      foo() {
        //do foo
      }
    }

    class Child extends Parent{
      constructor() {
        super();
      }
    }

    const child = new Child();
    const childSpy = sinon.spy(child, 'foo');

    child.foo();

    expect(childSpy.called).to.be.true; //true    

  });
});

希望这有帮助。

所以,我尝试了这个,得到了与您列出的不同的结果。在我的例子中,childSpy被称为,parentSpy不是,考虑到sinon的工作方式,这是我所期望的。所以我假设你把它们混在你的帖子里,然后从那里开始

这里发生的事情有点微妙,取决于sinon在一个物体上制造间谍时实际做了什么

执行此行时:

const childSpy = sinon.spy(Child.prototype, 'foo')
Sinon首先访问
Child.prototype
上名为
foo的属性。
此属性实际上不存在于
Child.prototype
上,因此JavaScript将原型链升级到
Parent.prototype,
,并在那里找到此类属性

因此,sinon获得了对原始函数的引用,该函数存储在
Parent.prototype.foo
中。它将此函数包装在spy中,然后将其分配给
Child.prototype
作为
Child.prototype.foo

奇怪的是,
Child.prototype
以前没有自己对原始
foo
函数的引用,但现在它有了,这就是现在在
Child
实例上调用
foo
时将调用的

执行此行时:

const childSpy = sinon.spy(Child.prototype, 'foo')
const parentSpy=sinon.spy(Parent.prototype,“foo”)

Sinon在
Parent.prototype.foo
处访问函数,将其包装在spy中,并将spy分配给它。这似乎应该会影响spy在
Child.prototype.foo
中包装的函数,但事实并非如此。在那里找到的间谍仍然在包装原始的
Parent.prototype.foo

你可能会想改变间谍创建声明的顺序来回避这个问题,但你会发现西诺不允许这样做。无法包装已映射的方法。也就是说,如果某个东西已经是间谍,试图使用sinon来“侦察间谍”将抛出。这是有很好的理由的,尽管我确信在这种情况下它看起来令人沮丧

您没有访问类实例的权限似乎有些奇怪,但如果您真的必须这样做,解决此问题的一种方法是为子类提供自己的
foo
方法。它只需在super上使用相同的签名调用相同的方法:

class Parent{
    constructor(){}
    foo(){
        //do foo
    }
}

class Child extend Parent{
    constructor(){
        super();
    }

    foo(...args){
        return super.foo(...args)
    }
}

const childSpy = sinon.spy(Child.prototype, 'foo')
const parentSpy = sinon.spy(Parent.prototype, 'foo')


new Child().foo();

expect(childSpy).to.have.been.called;
expect(parentSpy).to.have.been.called;

这样做将使您的childSpy包装
Child.prototype.foo
,它将调用调用调用时父.prototype.foo的值。

感谢您的输入。不幸的是,我没有访问该实例的权限,我在问题中的示例是一个简化版本,从概念上展示了我的场景。