ES2016 Class, Sinon 存根构造函数

ES2016 Class, Sinon Stub Constructor

我正在尝试用 sinon 和 es2016 打断一个超级调用,但我运气不佳。知道为什么这不起作用吗?

运行 Node 6.2.2,这可能是其 classes/constructors.

实现的问题

.babelrc 文件:

{
  "presets": [
    "es2016"
  ],
  "plugins": [
    "transform-es2015-modules-commonjs",
    "transform-async-to-generator"
  ]
}

测试:

import sinon from 'sinon';

class Foo {
  constructor(message) {
    console.log(message)
  }
}

class Bar extends Foo {
  constructor() {
    super('test');
  }
}

describe('Example', () => {
  it('should stub super.constructor call', () => {
    sinon.stub(Foo.prototype, 'constructor');

    new Bar();

    sinon.assert.calledOnce(Foo.prototype.constructor);
  });
});

结果:

test
AssertError: expected constructor to be called once but was called 0 times
    at Object.fail (node_modules\sinon\lib\sinon\assert.js:110:29)
    at failAssertion (node_modules\sinon\lib\sinon\assert.js:69:24)
    at Object.assert.(anonymous function) [as calledOnce] (node_modules\sinon\lib\sinon\assert.js:94:21)
    at Context.it (/test/classtest.spec.js:21:18)

注意:这个问题似乎只发生在构造函数中。我可以毫无问题地监视从父 class 继承的方法。

您需要 spy 而不是 stub

sinon.spy(Foo.prototype, 'constructor');

describe('Example', () => {
  it('should stub super.constructor call', () => {
    const costructorSpy = sinon.spy(Foo.prototype, 'constructor');
    new Bar();
    expect(costructorSpy.callCount).to.equal(1);
  });
});

*****更新****** 上面没有按预期工作,我以这种方式添加并且现在正在工作。

 describe('Example', () => {
    it('should stub super.constructor call', () => {
      const FooStub = spy(() => sinon.createStubInstance(Foo));
      expect(FooStub).to.have.been.calledWithNew;
    });
 });

我也不行。我管理了一个适合我的解决方法,我也使用间谍:

class FakeSchema {
  constructor(newCar) {
    this.constructorCallTest();
    this.name = newCar.name;
  }

  constructorCallTest() {
    mochaloggger.log('constructor was called');
  }

}

// spy that tracks the contsructor call
var fakeSchemaConstrSpy = sinon.spy(FakeCarSchema.prototype,'constructorCallTest');

希望对您有所帮助

如果您在浏览器环境中,以下内容也适用:

let constructorSpy = sinon.spy(window, 'ClassName');

例如,这将适用于 Jasmine。

Mocha 改为在 Node 环境中运行,没有 window。您要查找的变量是 global

由于 JavaScript 实现继承的方式,您需要设置子类的原型。

const sinon = require("sinon");

class Foo {
  constructor(message) {
    console.log(message);
  }
}

class Bar extends Foo {
  constructor() {
    super('test');
  }
}

describe('Example', () => {
  it('should stub super.constructor call', () => {
    const stub = sinon.stub().callsFake();
    Object.setPrototypeOf(Bar, stub);

    new Bar();

    sinon.assert.calledOnce(stub);
  });
});

添加到文山的中,有一个步骤可能会被忽略,将父class存根并将原来的父class替换为setPrototypeOf

此外,为避免它破坏后续测试,最好在末尾 设置原始父级 class,例如:

const sinon = require("sinon");
    
class Foo {
  constructor(message) {
    console.log(message);
   }
}
    
class Bar extends Foo {
  constructor() {
    super('test');
  }
}
    
describe('Bar constructor', () => {
  it('should call super', () => {
    const stub = sinon.stub().callsFake();
    const original = Object.getPrototypeOf(Bar);  // Bar.__proto__ === Foo
    

    Object.setPrototypeOf(Bar, stub);             // Bar.__proto__ === stub
    
    new Bar();
    
    sinon.assert.calledOnce(stub);
    Object.setPrototypeOf(Bar, original);         // Bar.__proto__ === Foo

  });
});

加法是

// saving the reference to the original parent class:
const original = Object.getPrototypeOf(Bar);
// setting back the original parent class after stubbing and the assertion:
Object.setPrototypeOf(Bar, original);