I have a class that leverages helper classes, and I'd like to verify it constructs those objects correctly. So, I'm trying to stub the "constructor" method in my classes, but I'm clearly not doing it right:
"use strict";
class Collaborator {
constructor(settings) {
console.log("Don't want this to be called!")
this.settings = settings;
}
}
class ThingToTest {
constructor(settings) {
this.helper = new Collaborator(settings);
}
}
const assert = require("assert");
const sinon = require("sinon");
describe("ThingToTest", () => {
let settings = "all the things"
context("spying on constructor", () => {
let spy = sinon.spy(Collaborator, "constructor")
after(() => spy.restore())
describe("constructor", () => {
it("creates a Collaborator with provided settings", () => {
new ThingToTest(settings);
sinon.assert.calledWith(spy, settings)
})
})
})
context("spying on prototype constructor", () => {
let spy = sinon.spy(Collaborator.prototype, "constructor")
after(() => spy.restore())
describe("constructor", () => {
it("creates a Collaborator with provided settings", () => {
new ThingToTest(settings);
sinon.assert.calledWith(spy, settings)
})
})
})
context("stub constructor", () => {
before(() => {
sinon.stub(Collaborator, "constructor", (settings) => {
console.log("This should be called so we can inspect", settings);
})
})
after(() => { Collaborator.constructor.restore() })
describe("constructor", () => {
it("creates a Collaborator with provided settings", () => {
new ThingToTest(settings);
})
})
})
context("stub prototype constructor", () => {
before(() => {
sinon.stub(Collaborator.prototype, "constructor", (settings) => {
console.log("This should be called so we can inspect", settings);
})
})
after(() => { Collaborator.prototype.constructor.restore() })
describe("constructor", () => {
it("creates a Collaborator with provided settings", () => {
new ThingToTest(settings);
})
})
})
})
Running this produces these (undesirable) results:
ThingToTest
spying on constructor
constructor
Don't want this to be called!
1) creates a Collaborator with provided settings
spying on prototype constructor
constructor
Don't want this to be called!
2) creates a Collaborator with provided settings
stub constructor
constructor
Don't want this to be called!
✓ creates a Collaborator with provided settings
stub prototype constructor
constructor
Don't want this to be called!
✓ creates a Collaborator with provided settings
It seems like stubbing is sort of working since putting the stub tests before the spy tests errors with the dreaded "TypeError: Attempted to wrap constructor which is already wrapped". So, clearly figuring out how to mock the Collaborators constructor is only half of what I'm doing wrong . . . I'm not restoring the constructor correctly either. Any suggestions?
This is not the solution I want, however for the time being I may end up using this (but please, if you have a suggestion, save me from myself):
This passes and verifies the Collaborator has the correct settings set. But now if I want to refactor the Collaborator constructor, I'm going to break the ThingToTest. Again, I'm still holding out hope someone can suggest a way to actually unit test this class!