如何使用Sinon存根ES6类构造函数

问题描述 投票:4回答:1

我正在尝试使用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;
        });
    });
});
javascript sinon es6-class
1个回答
0
投票

已经超过2年,这意味着很难。 :)

当很难执行时,则需要重构代码。

下面的示例可行,但可能无法在现实世界中使用(需要在定义Foo之前​​将Bar定义为存根)。

突出显示:

  • stub calledWithNew()的用法,以检查Bar是否以新的名称调用。
  • 不使用arrow functions
  • 使用柴的expect instanceof,因为Foo构造函数将添加属性bar,然后,可以添加其他期望以检查属性栏,这意味着检查Foo的构造函数是否运行。
// @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();
  }
}

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.