I'm trying to stub out a super call with sinon, and es2016 but I'm not having much luck. Any ideas why this isn't working?
Running Node 6.2.2, this might be an issue with its implementation of classes/constructors.
.babelrc file:
{
"presets": [
"es2016"
],
"plugins": [
"transform-es2015-modules-commonjs",
"transform-async-to-generator"
]
}
Test:
import sinon from 'sinon';
class Foo {
constructor(message) {
console.log(message)
}
}
class Bar extends Foo {
constructor() {
super('test');
}
}
describe('Example', () => {
it('should stub super.constructor call', () => {
sinon.stub(Foo.prototype, 'constructor');
new Bar();
sinon.assert.calledOnce(Foo.prototype.constructor);
});
});
Result:
test
AssertError: expected constructor to be called once but was called 0 times
at Object.fail (node_modules\sinon\lib\sinon\assert.js:110:29)
at failAssertion (node_modules\sinon\lib\sinon\assert.js:69:24)
at Object.assert.(anonymous function) [as calledOnce] (node_modules\sinon\lib\sinon\assert.js:94:21)
at Context.it (/test/classtest.spec.js:21:18)
Note: this issue seems to only happen for constructors. I can spy on methods inherited from the parent class without any issues.
to stub the myMethod instance method in the YourClass class. We call callsFake with a callback that returns the value we want for the fake method. sinon. stub(YourClass, "myStaticMethod").
If you need to check that a certain value is set before a function is called, you can use the third parameter of stub to insert an assertion into the stub: var object = { }; var expectedValue = 'something'; var func = sinon. stub(example, 'func', function() { assert. equal(object.
The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.
To stub a promise with sinon and JavaScript, we can return a promise with a stub. import sinon from "sinon"; const sandbox = sinon. sandbox. create(); const promiseResolved = () => sandbox.
You'll need to setPrototypeOf the subClass due to the way JavaScript implements inheritance.
const sinon = require("sinon");
class Foo {
constructor(message) {
console.log(message);
}
}
class Bar extends Foo {
constructor() {
super('test');
}
}
describe('Example', () => {
it('should stub super.constructor call', () => {
const stub = sinon.stub().callsFake();
Object.setPrototypeOf(Bar, stub);
new Bar();
sinon.assert.calledOnce(stub);
});
});
You need to spy
instead of stub
,
sinon.spy(Foo.prototype, 'constructor');
describe('Example', () => {
it('should stub super.constructor call', () => {
const costructorSpy = sinon.spy(Foo.prototype, 'constructor');
new Bar();
expect(costructorSpy.callCount).to.equal(1);
});
});
*****Update****** Above was not working as expected, I added this way and is working now.
describe('Example', () => {
it('should stub super.constructor call', () => {
const FooStub = spy(() => sinon.createStubInstance(Foo));
expect(FooStub).to.have.been.calledWithNew;
});
});
Adding to the accepted answer of Wenshan, there is one step that may be overlooked when stubbing the parent class and replacing the original parent class with setPrototypeOf
.
💡 Additionally, to avoid it breaking the succeeding tests it is a good idea to set back the original parent class at the end, like:
const sinon = require("sinon");
class Foo {
constructor(message) {
console.log(message);
}
}
class Bar extends Foo {
constructor() {
super('test');
}
}
describe('Bar constructor', () => {
it('should call super', () => {
const stub = sinon.stub().callsFake();
const original = Object.getPrototypeOf(Bar); // Bar.__proto__ === Foo
Object.setPrototypeOf(Bar, stub); // Bar.__proto__ === stub
new Bar();
sinon.assert.calledOnce(stub);
Object.setPrototypeOf(Bar, original); // Bar.__proto__ === Foo
});
});
The addition is
// saving the reference to the original parent class:
const original = Object.getPrototypeOf(Bar);
// setting back the original parent class after stubbing and the assertion:
Object.setPrototypeOf(Bar, original);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With