Sinon: reset() does not reset a stub

Created on 15 Aug 2015  ·  8Comments  ·  Source: sinonjs/sinon

reset resets only a spy but not a stub

Consider this code:

var sinon = require('sinon');
var stub = sinon.stub();
stub.withArgs(1).returns('Bye');
stub.reset();
stub.returns('Hello');
console.log('stub(1)', stub(1));

it prints

stub(1) Bye

if I change stub.reset(); to stub.resetBehavior(); it works as expected, i.e. prints stub(1) Hello.
But resetBehavior is not documented (#267) and it would be more consistent and natural if reset works for both spies and stubs.

Another option is to change stub.reset(); to stub = sinon.stub();.
But It is not always feasible to create a new stub in each test. Consider this example:

var stub = spy.stub();
var obj = createExpensiveObject(stub);

it('test1', function() {
  // setup stub in some way
  obj.test1();
});

it('test2', function() {
  // setup stub in a different way
  obj.test2();
});

Most helpful comment

Now you can only call .resetBehvaior() alone. You cannot reset the call counts without resetting the behavior. This seems like a regression.

That's a good point.

Perhaps it would be better if we expanded the api a bit.

// resets both call history and behaviour
stub.reset();

// reset call history
stub.resetHistory();

// reset behaviour
stub.resetBehavior()

All 8 comments

This ticket is a bit convoluted. Are you reporting a bug or requesting a change?

Stubs are intentionally cheap to create, so if you want fresh behaviour, just create another one?

I would consider it a change request, which is

If reset() is called on a stub, it should reset it to an initial state

One could consider it also a design bug because a stub (being also a spy) has a reset() function but it only resets only the spy part of it.

While stubs are cheap to create, the objects where one needs to inject them might not be so cheap. So just creating a new stub might not be enough if need also to recreate the object where you inject the new stub.
See my example above. I need to use a different stub in each test (which is usually the case). To do this now, I have to call createExpensiveObject for each test, just to pass it the new stub.

Did this just take away a feature? Before you could have acheived this by calling:

stub.reset();
stub.resetBehvaior();

Now you can only call .resetBehvaior() alone. You cannot reset the call counts without resetting the behavior. This seems like a regression.

Now you can only call .resetBehvaior() alone. You cannot reset the call counts without resetting the behavior. This seems like a regression.

That's a good point.

Perhaps it would be better if we expanded the api a bit.

// resets both call history and behaviour
stub.reset();

// reset call history
stub.resetHistory();

// reset behaviour
stub.resetBehavior()

Seems reasonable

@mroderick That seems solid to me.

So that the idea is not lost, I've created issue #863 for adding .resetHistory to the api.

This change should be called out in the release notes as a breaking change. This is a change to the expected behavior of .reset().

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fearphage picture fearphage  ·  4Comments

byohay picture byohay  ·  3Comments

optimatex picture optimatex  ·  4Comments

NathanHazout picture NathanHazout  ·  3Comments

akdor1154 picture akdor1154  ·  4Comments