-
-
Notifications
You must be signed in to change notification settings - Fork 771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix onCall(#) with chained behaviors #1738
Conversation
Currently returns doesn't work with that combination See issue sinonjs#1736
e.g. this code: stub.onCall(0).yields(x).returns(y) will once again both call the callback with x and return y. This feature was present in v1.17.7, but lost somewhere between there and v4.4.5 Fixes sinonjs#1736
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks fine. Good to have documenting tests.
I somewhat agree with you, but how would one make a stub that returns bar
in most cases, but 'foo' in the 42nd call when using your fix?
@@ -101,7 +101,7 @@ function callCallback(behavior, args) { | |||
|
|||
var proto = { | |||
create: function create(stub) { | |||
var behavior = extend({}, proto); | |||
var behavior = extend(stub.bind(), proto); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this do? I am guessing this is an easy way of wrapping the stub in a closure so you can change the copy instead of the original. am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We could replace it with
var behavior = extend(function(){
var args = Array.prototype.slice.call(arguments);
return stub.apply(null, args);
}, proto);
But the .bind version is more concise.
We don't want to extend the stub directly because that would overwrite other things.
Like this: var stub = sinon.stub();
stub.returns('foo');
stub.onCall(42).returns('bar'); (The second two lines could be swapped without changing the behavior.) Or, a chained version: var stub = sinon.stub().returns('foo').onCall(42).returns('bar'); (The behavior depends on the order here.) We could perhaps add a method to get back to the default behavior, e.g. var stub = sinon.stub().onCall(42).returns('bar').otherwise().returns('foo'); and And, like I said, this change restores the behavior that was present in Sinon 1.x. I'm not exactly sure when it changed, but I'm sure we could track it down if it matters. |
@mroderick This seemed fine and I finally understood the nuances of the implications, but I am not sure this should result in a new major or a patch! It is an API change, but as the previous change never was official/published I regard this as more of a bugfix that gives us the old behaviour back. |
I chose to release this as 4.4.10, given that I think this should be regarded as a bug fix. |
And thanks, @nfriedly, for the great work! |
Good work team! |
Purpose (TL;DR) - mandatory
Restores previous Sinon behavior and fixes issue #1736 by making all chained behaviors (yields, returns, throws, etc.) added after an
.onCall(#)
apply to that call rather than only the first behavior applying, and subsequent ones reverting to the default behavior.Background (Problem in detail) - optional
As mentioned in the original issue, in previous versions of Sinon, the following code added a
yeilds
and areturns
behavior to call 0:However, in the current release of Sinon, that code would cause the first call to yield x and return undefined, and then all subsequent calls would return y.
The codebase I'm working on currently, uses the above pattern in numerous places for mocking
http.request
(which both returns and yields), and upgrading to the current version of Sinon caused a number of tests to start failing.Solution - optional
behaviorMethods always return
this
(the behavior object) instead of the original stub. I also changed the behavior object to be a function that calls through to the original stub.WARNING
It's possible that some users inadvertently depend on the buggy behavior with code such as this:
In the current release, the first call will return 'foo', and subsequent calls will return 'bar'. With the fix, it will return 'bar' and then undefined. However, I would argue that the above code is buggy and this fix merely exposes that bug, and therfore this fix shouldn't constitute a breaking change.
How to verify - mandatory
npm install
npm test
Checklist for author
npm run lint
passes