Cleaning up sinon stubs easily

Viewed 112763

Is there a way to easily reset all sinon spys mocks and stubs that will work cleanly with mocha's beforeEach blocks.

I see sandboxing is an option but I do not see how you can use a sandbox for this

beforeEach ->
  sinon.stub some, 'method'
  sinon.stub some, 'mother'

afterEach ->
  # I want to avoid these lines
  some.method.restore()
  some.other.restore()

it 'should call a some method and not other', ->
  some.method()
  assert.called some.method
9 Answers

Previous answers suggest using sandboxes to accomplish this, but according to the documentation:

Since sinon@5.0.0, the sinon object is a default sandbox.

That means that cleaning up your stubs/mocks/spies is now as easy as:

var sinon = require('sinon');

it('should do my bidding', function() {
    sinon.stub(some, 'method');
}

afterEach(function () {
    sinon.restore();
});

Create a sandbox which will act as a black box container for all your spies, stubs, mocks and fakes.

All you have to do is create a sandbox in the very first describe block so that, it is accessible throughout all the test cases. And once you are done with all the test cases you should release the original methods and clean up the stubs using the method sandbox.restore() in the afterEach hook so that at runtime it releases held up resources afterEach test case is passed or failed.

Here is an example:

 describe('MyController', () => {
    //Creates a new sandbox object
    const sandbox = sinon.createSandbox();
    let myControllerInstance: MyController;

    let loginStub: sinon.SinonStub;
    beforeEach(async () => {
        let config = {key: 'value'};
        myControllerInstance = new MyController(config);
        loginStub = sandbox.stub(ThirdPartyModule, 'login').resolves({success: true});
    });
    describe('MyControllerMethod1', () => {
        it('should run successfully', async () => {
            loginStub.withArgs({username: 'Test', password: 'Test'}).resolves();
            let ret = await myControllerInstance.run();
            expect(ret.status).to.eq('200');
            expect(loginStub.called).to.be.true;
        });
    });
    afterEach(async () => {
        //clean and release the original methods afterEach test case at runtime
        sandbox.restore(); 
    });
});

below will reset all the stubs and nested stubs.

sinon.reset();

or you do NameOfFunctiontionYouWantToReset.resetHistory();

like addingStub.resetHistory();

Related