Skip to content

Commit 19bd99f

Browse files
authored
Use no-op for every function when restoring instances (#2499)
* issue-2477 Use no-op for every function when restoring instances * Change wording to not depend on mutator type in tests
1 parent 8663ffa commit 19bd99f

File tree

6 files changed

+50
-10
lines changed

6 files changed

+50
-10
lines changed

lib/sinon/stub.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ stub.createStubInstance = function (constructor, overrides) {
131131
throw new TypeError("The constructor should be a function.");
132132
}
133133

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

136141
forEach(Object.keys(overrides || {}), function (propertyName) {
137142
if (propertyName in stubbedObject) {

lib/sinon/util/core/walk-object.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@ var functionName = require("@sinonjs/commons").functionName;
55
var getPropertyDescriptor = require("./get-property-descriptor");
66
var walk = require("./walk");
77

8-
function walkObject(predicate, object, filter) {
8+
/**
9+
* A utility that allows traversing an object, applying mutating functions on the properties
10+
*
11+
* @param {Function} mutator called on each property
12+
* @param {object} object the object we are walking over
13+
* @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property
14+
* @returns {void} nothing
15+
*/
16+
function walkObject(mutator, object, filter) {
917
var called = false;
10-
var name = functionName(predicate);
18+
var name = functionName(mutator);
1119

1220
if (!object) {
1321
throw new Error(
@@ -26,17 +34,19 @@ function walkObject(predicate, object, filter) {
2634
if (filter) {
2735
if (filter(object, prop)) {
2836
called = true;
29-
predicate(object, prop);
37+
mutator(object, prop);
3038
}
3139
} else {
3240
called = true;
33-
predicate(object, prop);
41+
mutator(object, prop);
3442
}
3543
}
3644
});
3745

3846
if (!called) {
39-
throw new Error(`Expected to ${name} methods on object but found none`);
47+
throw new Error(
48+
`Found no methods on object to which we could apply mutations`
49+
);
4050
}
4151

4252
return object;

test/restore-object-test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ describe("restore-object", function () {
4444
meh: "okay",
4545
});
4646
},
47-
{ message: "Expected to restore methods on object but found none" }
47+
{
48+
message:
49+
"Found no methods on object to which we could apply mutations",
50+
}
4851
);
4952
});
5053

test/sandbox-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,25 @@ describe("Sandbox", function () {
391391
{ message: "Cannot stub foo. Property does not exist!" }
392392
);
393393
});
394+
395+
it("restores an instance where every function of the prototype has been replaced by a no-op (#2477)", function () {
396+
const sandbox = this.sandbox;
397+
398+
class SystemUnderTest {
399+
constructor() {
400+
this.privateGetter = () => 42;
401+
}
402+
getValue() {
403+
return this.privateGetter();
404+
}
405+
}
406+
407+
const stubInstance = sandbox.createStubInstance(SystemUnderTest);
408+
sandbox.restore();
409+
410+
refute.exception(stubInstance.getValue);
411+
assert.isUndefined(stubInstance.getValue());
412+
});
394413
});
395414

396415
describe(".stub", function () {

test/stub-test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3162,7 +3162,10 @@ describe("stub", function () {
31623162
function () {
31633163
createStubInstance(Class);
31643164
},
3165-
{ message: "Expected to stub methods on object but found none" }
3165+
{
3166+
message:
3167+
"Found no methods on object to which we could apply mutations",
3168+
}
31663169
);
31673170
});
31683171

test/util/core/walk-object-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe("util/core/walk-object", function () {
4646
},
4747
{
4848
message:
49-
"Expected to fnWithNoName methods on object but found none",
49+
"Found no methods on object to which we could apply mutations",
5050
}
5151
);
5252
});
@@ -65,7 +65,7 @@ describe("util/core/walk-object", function () {
6565
},
6666
{
6767
message:
68-
"Expected to undefined methods on object but found none",
68+
"Found no methods on object to which we could apply mutations",
6969
}
7070
);
7171
});

0 commit comments

Comments
 (0)