Skip to content

Commit

Permalink
internal: extract sinon type checking into own module
Browse files Browse the repository at this point in the history
  • Loading branch information
fatso83 committed Mar 26, 2023
1 parent 7d60f2d commit eb02fb6
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 157 deletions.
5 changes: 3 additions & 2 deletions lib/sinon/create-stub-instance.js
@@ -1,10 +1,11 @@
"use strict";

const stub = require("./stub");
const sinonType = require("./util/core/sinon-type");
const forEach = require("@sinonjs/commons").prototypes.array.forEach;

function isStub(value) {
return value && value.throws && value.returns;
return sinonType.get(value) === "stub";
}

module.exports = function createStubInstance(constructor, overrides) {
Expand All @@ -13,7 +14,7 @@ module.exports = function createStubInstance(constructor, overrides) {
}

const stubInstance = Object.create(constructor.prototype);
stubInstance[Symbol.for("SinonType")] = "StubInstance";
sinonType.set(stubInstance, "stub-instance");

const stubbedObject = stub(stubInstance);

Expand Down
3 changes: 3 additions & 0 deletions lib/sinon/stub.js
Expand Up @@ -12,6 +12,7 @@ var spy = require("./spy");
var extend = require("./util/core/extend");
var getPropertyDescriptor = require("./util/core/get-property-descriptor");
var isEsModule = require("./util/core/is-es-module");
var sinonType = require("./util/core/sinon-type");
var wrapMethod = require("./util/core/wrap-method");
var throwOnFalsyObject = require("./throw-on-falsy-object");
var valueToString = require("@sinonjs/commons").valueToString;
Expand Down Expand Up @@ -58,6 +59,8 @@ function createStub(originalFunc) {
id: `stub#${uuid++}`,
});

sinonType.set(proxy, "stub");

return proxy;
}

Expand Down
22 changes: 22 additions & 0 deletions lib/sinon/util/core/sinon-type.js
@@ -0,0 +1,22 @@
"use strict";

const sinonTypeSymbolProperty = Symbol("SinonType");

module.exports = {
/**
* Set the type of a Sinon object to make it possible to identify it later at runtime
*
* @param {object|Function} object object/function to set the type on
* @param {string} type the named type of the object/function
*/
set(object, type) {
Object.defineProperty(object, sinonTypeSymbolProperty, {
value: type,
configurable: false,
enumerable: false,
});
},
get(object) {
return object && object[sinonTypeSymbolProperty];
},
};
3 changes: 2 additions & 1 deletion lib/sinon/util/core/wrap-method.js
Expand Up @@ -4,6 +4,7 @@
const noop = () => {};
var getPropertyDescriptor = require("./get-property-descriptor");
var extend = require("./extend");
const sinonType = require("./sinon-type");
var hasOwnProperty =
require("@sinonjs/commons").prototypes.object.hasOwnProperty;
var valueToString = require("@sinonjs/commons").valueToString;
Expand Down Expand Up @@ -232,7 +233,7 @@ module.exports = function wrapMethod(object, property, method) {
}
}
}
if (object[Symbol.for("SinonType")] === "StubInstance") {
if (sinonType.get(object) === "stub-instance") {
// this is simply to avoid errors after restoring if something should
// traverse the object in a cleanup phase, ref #2477
object[property] = noop;
Expand Down
4 changes: 2 additions & 2 deletions test/create-stub-instance-test.js
Expand Up @@ -2,7 +2,7 @@

var referee = require("@sinonjs/referee");
var createStub = require("../lib/sinon/stub");
var createStubInstance = require("../lib/sinon/create-stub-instance")
var createStubInstance = require("../lib/sinon/create-stub-instance");
var assert = referee.assert;
var refute = referee.refute;

Expand Down Expand Up @@ -155,4 +155,4 @@ describe("createStubInstance", function () {
{ message: "Cannot stub foo. Property does not exist!" }
);
});
})
});
152 changes: 0 additions & 152 deletions test/stub-test.js
Expand Up @@ -2,7 +2,6 @@

var referee = require("@sinonjs/referee");
var createStub = require("../lib/sinon/stub");
var createStubInstance = require("../lib/sinon/create-stub-instance")
var createSpy = require("../lib/sinon/spy");
var createProxy = require("../lib/sinon/proxy");
var match = require("@sinonjs/samsam").createMatcher;
Expand Down Expand Up @@ -3139,157 +3138,6 @@ describe("stub", function () {
});
});

describe(".createStubInstance", function () {
it("stubs existing methods", function () {
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};

var stub = createStubInstance(Class);
stub.method.returns(3);
assert.equals(3, stub.method());
});

it("throws with no methods to stub", function () {
var Class = function () {
return;
};

assert.exception(
function () {
createStubInstance(Class);
},
{
message:
"Found no methods on object to which we could apply mutations",
}
);
});

it("doesn't call the constructor", function () {
var Class = function (a, b) {
var c = a + b;
throw c;
};
Class.prototype.method = function () {
return;
};

var stub = createStubInstance(Class);
refute.exception(function () {
stub.method(3);
});
});

it("retains non function values", function () {
var TYPE = "some-value";
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};
Class.prototype.type = TYPE;

var stub = createStubInstance(Class);
assert.equals(TYPE, stub.type);
});

it("has no side effects on the prototype", function () {
var proto = {
method: function () {
throw new Error("error");
},
};
var Class = function () {
return;
};
Class.prototype = proto;

var stub = createStubInstance(Class);
refute.exception(stub.method);
assert.exception(proto.method);
});

it("throws exception for non function params", function () {
var types = [{}, 3, "hi!"];

for (var i = 0; i < types.length; i++) {
// yes, it's silly to create functions in a loop, it's also a test
// eslint-disable-next-line no-loop-func
assert.exception(function () {
createStubInstance(types[i]);
});
}
});

it("allows providing optional overrides", function () {
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};

var stub = createStubInstance(Class, {
method: createStub().returns(3),
});

assert.equals(3, stub.method());
});

it("allows providing optional returned values", function () {
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};

var stub = createStubInstance(Class, {
method: 3,
});

assert.equals(3, stub.method());
});

it("allows providing null as a return value", function () {
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};

var stub = createStubInstance(Class, {
method: null,
});

assert.equals(null, stub.method());
});

it("throws an exception when trying to override non-existing property", function () {
var Class = function () {
return;
};
Class.prototype.method = function () {
return;
};

assert.exception(
function () {
createStubInstance(Class, {
foo: createStub().returns(3),
});
},
{ message: "Cannot stub foo. Property does not exist!" }
);
});
});

describe(".callThrough", function () {
it("does not call original function when arguments match conditional stub", function () {
// We need a function here because we can't wrap properties that are already stubs
Expand Down

0 comments on commit eb02fb6

Please sign in to comment.