Skip to content

Commit

Permalink
Add getters/setters stub behaviors
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfcosta committed Mar 11, 2017
1 parent e0cfccc commit 278c2ce
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 23 deletions.
20 changes: 20 additions & 0 deletions lib/sinon/default-behaviors.js
Expand Up @@ -163,6 +163,26 @@ module.exports = {

callThrough: function callThrough(fake) {
fake.callsThrough = true;
},

get: function get(fake, getterFunction) {
var rootStub = fake.stub || fake;

Object.defineProperty(rootStub.rootObj, rootStub.propName, {
get: getterFunction
});

return fake;
},

set: function set(fake, setterFunction) {
var rootStub = fake.stub || fake;

Object.defineProperty(rootStub.rootObj, rootStub.propName, { // eslint-disable-line accessor-pairs
set: setterFunction
});

return fake;
}
};

Expand Down
21 changes: 18 additions & 3 deletions lib/sinon/stub.js
Expand Up @@ -5,6 +5,7 @@ var behaviors = require("./default-behaviors");
var spy = require("./spy");
var extend = require("./util/core/extend");
var functionToString = require("./util/core/function-to-string");
var getPropertyDescriptor = require("./util/core/get-property-descriptor");
var wrapMethod = require("./util/core/wrap-method");
var stubEntireObject = require("./stub-entire-object");
var stubDescriptor = require("./stub-descriptor");
Expand All @@ -13,24 +14,38 @@ var throwOnFalsyObject = require("./throw-on-falsy-object");
function stub(object, property, descriptor) {
throwOnFalsyObject.apply(null, arguments);

var actualDescriptor = getPropertyDescriptor(object, property);
var isStubbingEntireObject = typeof property === "undefined" && typeof object === "object";
var isCreatingNewStub = !object && typeof property === "undefined";
var isStubbingDescriptor = object && property && Boolean(descriptor);
var isStubbingNonFuncProperty = typeof object === "object"
&& typeof property !== "undefined"
&& (typeof actualDescriptor === "undefined"
|| typeof actualDescriptor.value !== "function")
&& typeof descriptor === "undefined";
var isStubbingExistingMethod = !isStubbingDescriptor
&& typeof object === "object"
&& typeof object[property] === "function";
&& typeof actualDescriptor !== "undefined"
&& typeof actualDescriptor.value === "function";
var arity = isStubbingExistingMethod ? object[property].length : 0;

if (isStubbingEntireObject) {
return stubEntireObject(stub, object);
}

if (isStubbingDescriptor) {
return stubDescriptor.apply(null, arguments);
}

if (isCreatingNewStub) {
return stub.create();
}

if (isStubbingDescriptor) {
return stubDescriptor.apply(null, arguments);
if (isStubbingNonFuncProperty) {
var s = stub.create();
s.rootObj = object;
s.propName = property;
return s;
}

return wrapMethod(object, property, stub.create(arity));
Expand Down
102 changes: 82 additions & 20 deletions test/stub-test.js
Expand Up @@ -800,16 +800,6 @@ describe("stub", function () {
assert.isFalse(stub.called);
});

it("throws if property is not a function", function () {
var obj = { someProp: 42 };

assert.exception(function () {
createStub(obj, "someProp");
});

assert.equals(obj.someProp, 42);
});

it("successfully stubs falsey properties", function () {
var obj = { 0: function () { } };

Expand Down Expand Up @@ -943,16 +933,6 @@ describe("stub", function () {
});

describe("stubbed function", function () {
it("throws if stubbing non-existent property", function () {
var myObj = {};

assert.exception(function () {
createStub(myObj, "ouch");
});

refute.defined(myObj.ouch);
});

it("has toString method", function () {
var obj = { meth: function () {} };
createStub(obj, "meth");
Expand Down Expand Up @@ -2301,4 +2281,86 @@ describe("stub", function () {
assert.equals(reference, myObj);
});
});

describe(".get", function () {
it("allows users to stub getter functions for properties", function () {
var myObj = {
prop: "foo"
};

createStub(myObj, "prop").get(function () {
return "bar";
});

assert.equals(myObj.prop, "bar");
});

it("replaces old getters", function () {
var myObj = {
get prop() {
fail("should not call the old getter");
}
};

createStub(myObj, "prop").get(function () {
return "bar";
});

assert.equals(myObj.prop, "bar");
});

it("can set getters for non-existing properties", function () {
var myObj = {};

createStub(myObj, "prop").get(function () {
return "bar";
});

assert.equals(myObj.prop, "bar");
});
});

describe(".set", function () {
it("allows users to stub setter functions for properties", function () {
var myObj = {
prop: "foo"
};

createStub(myObj, "prop").set(function () {
myObj.example = "bar";
});

myObj.prop = "baz";

assert.equals(myObj.example, "bar");
});

it("replaces old setters", function () {
var myObj = { // eslint-disable-line accessor-pairs
set prop(val) {
fail("should not call the old setter");
}
};

createStub(myObj, "prop").set(function () {
myObj.example = "bar";
});

myObj.prop = "foo";

assert.equals(myObj.example, "bar");
});

it("can set setters for non-existing properties", function () {
var myObj = {};

createStub(myObj, "prop").set(function () {
myObj.example = "bar";
});

myObj.prop = "foo";

assert.equals(myObj.example, "bar");
});
});
});

0 comments on commit 278c2ce

Please sign in to comment.