Skip to content

Commit

Permalink
Fix sinonjs#1274: spy.withArgs(args...).callCount is incorrect
Browse files Browse the repository at this point in the history
1. Update matchingFake function in spy.js
   Rename to matchingFakes, and return not last one fake (pop()) but all
   fakes matched.
2. Move matchingFakes function into spyApi
   Because of calling by stub.js
3. Modify spyApi.invoke function
   Apply processing at function invoked to all matching fakes.
4. Modify part of calling matchingFake() in spyApi.withArgs
   Fit logic, affected by 1.
5. Update proto.create.functionStub in stub.js
   Try to get the function stub using spyApi.matchingFakes()
   and pop(), affected by 1.
  • Loading branch information
takasmiley committed Mar 2, 2017
1 parent 2e9bb09 commit a55ec1d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 24 deletions.
62 changes: 39 additions & 23 deletions lib/sinon/spy.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,6 @@ function spy(object, property, types) {
return wrapMethod(object, property, descriptor);
}

function matchingFake(fakes, args, strict) {
if (!fakes) {
return undefined;
}

var matchingFakes = fakes.filter(function (fake) {
return fake.matches(args, strict);
});

return matchingFakes.pop();
}

function incrementCallCount() {
this.called = true;
this.callCount += 1;
Expand Down Expand Up @@ -170,25 +158,30 @@ var spyApi = {
},

invoke: function invoke(func, thisValue, args) {
var matching = matchingFake(this.fakes, args);
var exception, returnValue;
var matchings = this.matchingFakes(args);
var currentCallId = callId++;
var exception, returnValue, i;

incrementCallCount.call(this);
push.call(this.thisValues, thisValue);
push.call(this.args, args);
push.call(this.callIds, callId++);
push.call(this.callIds, currentCallId);
if (matchings) {
for (i = 0; i < matchings.length; i++) {
incrementCallCount.call(matchings[i]);
push.call(matchings[i].thisValues, thisValue);
push.call(matchings[i].args, args);
push.call(matchings[i].callIds, currentCallId);
}
}

// Make call properties available from within the spied function:
createCallProperties.call(this);

try {
this.invoking = true;

if (matching) {
returnValue = matching.invoke(func, thisValue, args);
} else {
returnValue = (this.func || func).apply(thisValue, args);
}
returnValue = (this.func || func).apply(thisValue, args);

var thisCall = this.getCall(this.callCount - 1);
if (thisCall.calledWithNew() && typeof returnValue !== "object") {
Expand All @@ -202,6 +195,13 @@ var spyApi = {

push.call(this.exceptions, exception);
push.call(this.returnValues, returnValue);
if (matchings) {
for (i = 0; i < matchings.length; i++) {
push.call(matchings[i].exceptions, exception);
push.call(matchings[i].returnValues, returnValue);
}
}

var err = new ErrorConstructor();
// 1. Please do not get stack at this point. It's may be so very slow, and not actually used
// 2. PhantomJS does not serialize the stack trace until the error has been thrown:
Expand All @@ -210,6 +210,11 @@ var spyApi = {
throw err;
} catch (e) {/* empty */}
push.call(this.errorsWithCallStack, err);
if (matchings) {
for (i = 0; i < matchings.length; i++) {
push.call(matchings[i].errorsWithCallStack, err);
}
}

// Make return value and exception available in the calls:
createCallProperties.call(this);
Expand Down Expand Up @@ -271,10 +276,11 @@ var spyApi = {
var args = slice.call(arguments);

if (this.fakes) {
var match = matchingFake(this.fakes, args, true);
var matchings = this.matchingFakes(args, true);
var matching = matchings && matchings.pop();

if (match) {
return match;
if (matching) {
return matching;
}
} else {
this.fakes = [];
Expand Down Expand Up @@ -308,6 +314,16 @@ var spyApi = {
return fake;
},

matchingFakes: function (args, strict) {
if (!this.fakes) {
return undefined;
}

return this.fakes.filter(function (fake) {
return fake.matches(args, strict);
});
},

matches: function (args, strict) {
var margs = this.matchingArguments;

Expand Down
8 changes: 7 additions & 1 deletion lib/sinon/stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ var stubEntireObject = require("./stub-entire-object");
var stubDescriptor = require("./stub-descriptor");
var throwOnFalsyObject = require("./throw-on-falsy-object");

var slice = Array.prototype.slice;

function stub(object, property, descriptor) {
throwOnFalsyObject.apply(null, arguments);

Expand Down Expand Up @@ -65,7 +67,11 @@ var uuid = 0;
var proto = {
create: function create(stubLength) {
var functionStub = function () {
return getCurrentBehavior(functionStub).invoke(this, arguments);
var args = slice.call(arguments);
var matchings = functionStub.matchingFakes(args);

var fnStub = (matchings && matchings.pop()) || functionStub;
return getCurrentBehavior(fnStub).invoke(this, arguments);
};

functionStub.id = "stub#" + uuid++;
Expand Down

0 comments on commit a55ec1d

Please sign in to comment.