我正在尝试使用Sinon的存根类构造函数。
常规方法'omg'的存根可以正常工作,但是构造函数的存根未通过测试,因此将调用'real'构造函数而不是存根。
关于需要正确存根的语法的任何想法?
class Foo {
constructor() {
this.bar = new Bar();
}
omg() {
this.bar.omg();
}
}
class Bar {
constructor() {
console.log('In bar constructor');
}
omg() {
console.log('In bar omg');
}
}
const sandbox = sinon.createSandbox();
sandbox.stub(Bar.prototype, 'constructor');
sandbox.stub(Bar.prototype, 'omg');
describe('Foo', () => {
describe('Constructor', () => {
it('Should instantiate bar', () => {
const foo = new Foo();
expect(Bar.prototype.constructor.called).to.be.true;
});
});
describe('Omg', () => {
it("Should call Bar's omg method', () => {
const foo = new Foo();
foo.omg();
expect(Bar.prototype.omg.called).to.be.true;
});
});
});
已经超过2年,这意味着很难。 :)
当很难执行时,则需要重构代码。
下面的示例可行,但可能无法在现实世界中使用(需要在定义Foo之前将Bar定义为存根)。
突出显示:
// @file stackoverflow.js
const sinon = require('sinon');
const { expect } = require('chai');
const sandbox = sinon.createSandbox();
// Define Bar as a stub.
const Bar = sandbox.stub();
const BarOmgFn = sinon.fake();
Bar.prototype.omg = BarOmgFn;
// class Bar {
// constructor() {
// console.log('In bar constructor');
// }
// omg() {
// console.log('In bar omg');
// }
// }
class Foo {
constructor() {
this.bar = new Bar();
}
omg() {
this.bar.omg();
}
}
describe('Foo', function () {
after(function () {
sandbox.restore();
});
describe('Constructor', function () {
it('Should instantiate bar', function () {
const foo = new Foo();
// Check whether Bar called with new.
expect(Bar.calledWithNew()).to.equal(true);
// Check bar property.
expect(foo.bar).to.be.instanceOf(Bar);
});
});
describe('Omg', () => {
it("Should call Bar's omg method", function () {
const foo = new Foo();
foo.omg();
expect(BarOmgFn.calledOnce).to.equal(true);
});
});
});
使用mocha运行示例:
$ npx mocha stackoverflow.js
Foo
Constructor
✓ Should instantiate bar
Omg
✓ Should call Bar's omg method
2 passing (14ms)
$
从设计模式的角度来看,Foo类高度依赖于Bar类。重构可以使用dependency injection pattern。例如:对Foo类的简单更改,需要1个参数,它是Bar本身或Bar的实例。此更改使代码更易于测试。
class Foo {
// Now constructor need 1 argument
constructor(Bar) {
this.bar = new Bar();
}
omg() {
this.bar.omg();
}
}
希望这会有所帮助。