【问题标题】:Mocking/Stubbing `super` calls模拟/存根 `super` 调用
【发布时间】:2015-11-20 18:06:28
【问题描述】:

我想模拟 super 调用,尤其是一些 ES6 类中的构造函数。例如

import Bar from 'bar';

class Foo extends Bar {
  constructor(opts) {
    ...
    super(opts);
  }

  someFunc() {
    super.someFunc('asdf');
  }
}

然后在我的测试中,我想做类似的事情

import Foo from '../lib/foo';
import Bar from 'bar';

describe('constructor', function() {
  it('should call super', function() {
    let opts = Symbol('opts');
    let constructorStub = sinon.stub(Bar, 'constructor');
    new Foo(opts);
    sinon.assert.calledWith(constructorStub, opts);
  });
})

describe('someFunc', function() {
  it('should call super', function() {
    let funcStub = sinon.stub(Bar, 'someFunc');
    let foo = new Foo(opts);
    foo.someFunc();
    sinon.assert.calledWith(funcStub, 'asdf');
  });
})    

【问题讨论】:

  • super关键字作为函数调用时,调用基类构造函数。你的someFunc 样本应该是super.someFunc('asdf')
  • 不需要sinon.stub(Bar.prototype, 'someFunc');吗?
  • 不,您不能存根已经继承自的构造函数。您需要在 foo.js 中注入您的 Bar 监督版本。
  • 为什么要测试实现?为什么不只测试输入/输出?
  • @Amit:你说得对,这是我的例子中的一个错字。

标签: javascript unit-testing mocha.js ecmascript-6 sinon


【解决方案1】:

想通了,@Bergi 走在了正确的轨道上。 针对@naomik 的问题 - 我想要解决这个问题的主要目的有两个。首先,我不想实际实例化超类,只是验证我调用的是正确的东西。另一个原因(由于我试图简化示例,因此并没有真正实现),我真正关心的是我正在对opts 做某些事情,我想确保这些事情被正确执行到super 构造函数(例如,设置默认值)。

为了完成这项工作,我需要做sinon.stub(Bar.prototype, 'constructor');

这是一个更好的示例和工作测试。

// bar.js
import Memcached from 'memcached'

export default class Bar extends Memcached {
  constructor(opts) {
    super(opts);
  }
}

// foo.js
import Bar from './bar.js';
export default class Foo extends Bar {
  constructor(opts) {
    super(opts);
  }
}

// test.js
import Foo from './foo.js';
import Bar from './bar.js';
import Memcached from 'memcached';
import sinon from 'sinon';

let sandbox;
let memcachedStub;
const opts = '127.0.0.1:11211';

describe('constructors', function() {
  beforeEach(function() {
    sandbox = sinon.sandbox.create();
    memcachedStub = sandbox.stub(Memcached.prototype, 'constructor');
  });

  afterEach(function() {
    sandbox.restore();
  });

  describe('#bar', function() {
    it('should call super', function() {
      new Bar(opts);

      sinon.assert.calledOnce(memcachedStub);
      sinon.assert.calledWithExactly(memcachedStub, opts);
    });
  });

  describe('#foo', function() {
    it('should call super', function() {
      new Foo(opts);

      sinon.assert.calledOnce(memcachedStub);
      sinon.assert.calledWithExactly(memcachedStub, opts);
    });
  });
});

【讨论】:

  • 请注意,这是有效的,因为 Babel 通过 Class.prototype.constructor 查找实现了 ES6 super 调用,但原生 ES6 类通过 Object.getPrototypeOf(Class) 查找父构造函数,这在旧浏览器上不可填充.我猜你需要sandbox.stub(Memcached, '__proto__')
猜你喜欢
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多