[英]How to stub ES6 class constructors with Sinon
I'm trying stub class constructors with Sinon.我正在尝试使用 Sinon 的存根类构造函数。
The stub of the regular method 'omg' works fine, but the stub of the constructor fails the test, and the 'real' constructor is called instead of the stub.常规方法“omg”的存根工作正常,但构造函数的存根未通过测试,并且调用“真实”构造函数而不是存根。
Any ideas on what syntax I need to stub this correctly?关于我需要正确存根的语法有什么想法吗?
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; }); }); });
Its been more than 2 years, means this is hard.它已经超过2年了,这意味着这很难。 :) :)
When it is hard to do, then the code need refactoring.当它很难做到时,那么代码需要重构。
Below example works but may not usable at real world (need to define Bar as stub before define Foo).下面的示例有效,但在现实世界中可能无法使用(需要在定义 Foo 之前将 Bar 定义为存根)。
Highlight:亮点:
// @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);
});
});
});
Run the example using mocha:使用 mocha 运行示例:
$ npx mocha stackoverflow.js
Foo
Constructor
✓ Should instantiate bar
Omg
✓ Should call Bar's omg method
2 passing (14ms)
$
From design pattern point of view, class Foo is highly dependent to class Bar.从设计模式的角度来看,Foo 类高度依赖于 Bar 类。 Refactoring can use dependency injection pattern .重构可以使用依赖注入模式。 For example: simple change to class Foo, by require 1 argument, which is Bar itself or instance of Bar.例如:通过需要 1 个参数,即 Bar 本身或 Bar 的实例,对类 Foo 进行简单更改。 This change make the code easier to test.此更改使代码更易于测试。
class Foo {
// Now constructor need 1 argument
constructor(Bar) {
this.bar = new Bar();
}
omg() {
this.bar.omg();
}
}
Hope this helps.希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.