Side Effect in sinon.stub with returns().

583 views
Skip to first unread message

Rithwik Anand

unread,
Sep 9, 2014, 2:20:49 AM9/9/14
to sin...@googlegroups.com
Stubs are showing an undesirable side effect when used with returns. Below code snippet shows the expected behavior (using actual function scenario) and stub's behavior.

var actualFunc = function () {return ["internalContent"];};
var stubFunc = sinon.stub().returns(["internalContent"]);

var actualFuncReturn = actualFunc();
var stubFuncReturn = stubFunc();

actualFuncReturn
.push("sideEffect");
stubFuncReturn
.push("sideEffect");

console
.log(actualFunc()); //['internalContent'].
console
.log(stubFunc());  // ['internalContent', 'sideEffect'].


Is this a bug? If no, how do you justify this behavior?

Thanks,
Rithwik.

Maximilian Antoni

unread,
Sep 9, 2014, 2:53:26 AM9/9/14
to sin...@googlegroups.com
Yes, there are these cases. We can't create a copy of the object because you might want to return a specific instance of something. The copy would lead to other unexpected cases like === not working anymore.

Another example of this is when a function modifies an array argument. If you spy on it and try to assert the passes in arguments, it doesn't work.

-Max
--
You received this message because you are subscribed to the Google Groups "Sinon.JS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinonjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rithwik Anand

unread,
Sep 11, 2014, 11:18:39 AM9/11/14
to sin...@googlegroups.com
Thanks for the confirmation Max!

Since in my test case, avoiding side effects is more critical than doing equality checks, I do the following work around: 

var actualFunc = function () {return ["internalContent"];};
var stubFunc = sinon.stub();

var MAX_CALL_COUNT = 10; // Maximum invocations expected in current test case.
Array.apply(null, new Array(MAX_CALL_COUNT)).forEach(function (v, i) {
   stubFunc
.onCall(i).returns(["internalContent"]);
});

var actualFuncReturn = actualFunc();
var stubFuncReturn = stubFunc();

actualFuncReturn
.push("sideEffect");
stubFuncReturn
.push("sideEffect");

console
.log(actualFunc()); //['internalContent'].

console
.log(stubFunc()); // ['internalContent'].

Do you suggest any better way of doing it?

Thanks,
Rithwik. 

Maximilian Antoni

unread,
Sep 11, 2014, 2:39:27 PM9/11/14
to sin...@googlegroups.com
You could also implement custom logic yourself. That would read nicer, I think:

  sinon.spy(function () { return [ ... ]; })

or with a stub:

  sinon.stub(object, 'func', function () { return [ ... ]; })

-Max
Reply all
Reply to author
Forward
0 new messages