admin管理员组

文章数量:1289483

I would like to mock out super calls, especially constructors in some ES6 classes. For example

import Bar from 'bar';

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

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

And then in my test, I would like to do something like

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');
  });
})    

I would like to mock out super calls, especially constructors in some ES6 classes. For example

import Bar from 'bar';

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

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

And then in my test, I would like to do something like

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');
  });
})    
Share Improve this question edited Feb 15, 2019 at 11:10 aviit 2,1091 gold badge30 silver badges54 bronze badges asked Aug 26, 2015 at 15:43 FotiosFotios 3,6631 gold badge29 silver badges30 bronze badges 6
  • 2 When the super keyword is used as a function call, it calls the base class constructor function. Your someFunc sample should probably be super.someFunc('asdf') – Amit Commented Aug 26, 2015 at 16:04
  • Wouldn't it need to be sinon.stub(Bar.prototype, 'someFunc');? – Bergi Commented Aug 26, 2015 at 16:45
  • 1 No, you cannot stub a constructor that has already been inherited from. You'd need to inject your supervised version of Bar in foo.js. – Bergi Commented Aug 26, 2015 at 16:46
  • 1 Why are you testing implementation? Why not just test input/output? – Mulan Commented Aug 26, 2015 at 17:17
  • @Amit: You're right, that was a typo in my example. – Fotios Commented Aug 26, 2015 at 17:25
 |  Show 1 more ment

1 Answer 1

Reset to default 9

Figured it out, and @Bergi was on the right track. In reponse to @naomik's question - My main purpose for wanting to stub this out was two fold. First, I didn't want to actually instantiate the super class, merely validate that I was calling the proper thing. The other reason (which didn't really e through since I was trying to simplify the example), was that what I really cared about was that I was doing certain things to opts that I wanted to make sure were carried through properly to the super constructor (for example, setting default values).

To make this work, I needed to dosinon.stub(Bar.prototype, 'constructor');

This is a better example and working test.

// 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);
    });
  });
});

本文标签: javascriptMockingStubbing super callsStack Overflow