Skip to content

Commit

Permalink
Use no-op for every function when restoring instances (#2499)
Browse files Browse the repository at this point in the history
* issue-2477 Use no-op for every function when restoring instances
* Change wording to not depend on mutator type in tests
  • Loading branch information
fatso83 committed Mar 12, 2023
1 parent 8663ffa commit 19bd99f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 10 deletions.
7 changes: 6 additions & 1 deletion lib/sinon/stub.js
Expand Up @@ -131,7 +131,12 @@ stub.createStubInstance = function (constructor, overrides) {
throw new TypeError("The constructor should be a function.");
}

var stubbedObject = stub(Object.create(constructor.prototype));
// eslint-disable-next-line no-empty-function
const noop = () => {};
const defaultNoOpInstance = Object.create(constructor.prototype);
walkObject((obj, prop) => (obj[prop] = noop), defaultNoOpInstance);

const stubbedObject = stub(defaultNoOpInstance);

forEach(Object.keys(overrides || {}), function (propertyName) {
if (propertyName in stubbedObject) {
Expand Down
20 changes: 15 additions & 5 deletions lib/sinon/util/core/walk-object.js
Expand Up @@ -5,9 +5,17 @@ var functionName = require("@sinonjs/commons").functionName;
var getPropertyDescriptor = require("./get-property-descriptor");
var walk = require("./walk");

function walkObject(predicate, object, filter) {
/**
* A utility that allows traversing an object, applying mutating functions on the properties
*
* @param {Function} mutator called on each property
* @param {object} object the object we are walking over
* @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property
* @returns {void} nothing
*/
function walkObject(mutator, object, filter) {
var called = false;
var name = functionName(predicate);
var name = functionName(mutator);

if (!object) {
throw new Error(
Expand All @@ -26,17 +34,19 @@ function walkObject(predicate, object, filter) {
if (filter) {
if (filter(object, prop)) {
called = true;
predicate(object, prop);
mutator(object, prop);
}
} else {
called = true;
predicate(object, prop);
mutator(object, prop);
}
}
});

if (!called) {
throw new Error(`Expected to ${name} methods on object but found none`);
throw new Error(
`Found no methods on object to which we could apply mutations`
);
}

return object;
Expand Down
5 changes: 4 additions & 1 deletion test/restore-object-test.js
Expand Up @@ -44,7 +44,10 @@ describe("restore-object", function () {
meh: "okay",
});
},
{ message: "Expected to restore methods on object but found none" }
{
message:
"Found no methods on object to which we could apply mutations",
}
);
});

Expand Down
19 changes: 19 additions & 0 deletions test/sandbox-test.js
Expand Up @@ -391,6 +391,25 @@ describe("Sandbox", function () {
{ message: "Cannot stub foo. Property does not exist!" }
);
});

it("restores an instance where every function of the prototype has been replaced by a no-op (#2477)", function () {
const sandbox = this.sandbox;

class SystemUnderTest {
constructor() {
this.privateGetter = () => 42;
}
getValue() {
return this.privateGetter();
}
}

const stubInstance = sandbox.createStubInstance(SystemUnderTest);
sandbox.restore();

refute.exception(stubInstance.getValue);
assert.isUndefined(stubInstance.getValue());
});
});

describe(".stub", function () {
Expand Down
5 changes: 4 additions & 1 deletion test/stub-test.js
Expand Up @@ -3162,7 +3162,10 @@ describe("stub", function () {
function () {
createStubInstance(Class);
},
{ message: "Expected to stub methods on object but found none" }
{
message:
"Found no methods on object to which we could apply mutations",
}
);
});

Expand Down
4 changes: 2 additions & 2 deletions test/util/core/walk-object-test.js
Expand Up @@ -46,7 +46,7 @@ describe("util/core/walk-object", function () {
},
{
message:
"Expected to fnWithNoName methods on object but found none",
"Found no methods on object to which we could apply mutations",
}
);
});
Expand All @@ -65,7 +65,7 @@ describe("util/core/walk-object", function () {
},
{
message:
"Expected to undefined methods on object but found none",
"Found no methods on object to which we could apply mutations",
}
);
});
Expand Down

0 comments on commit 19bd99f

Please sign in to comment.