Sinon error Attempted to wrap function which is already wrapped

86,973

Solution 1

You should restore the getObj in after() function, please try it as below.

describe('App Functions', function(){
    var mockObj;
    before(function () {
            mockObj = sinon.stub(testApp, 'getObj', () => {
                 console.log('this is sinon test 1111');
            });
    });
    after(function () {
        testApp.getObj.restore(); // Unwraps the spy
    });
    it('get results',function(done) {
        testApp.getObj();
    });
});
describe('App Errors', function(){
    var mockObj;
    before(function () {
            mockObj = sinon.stub(testApp, 'getObj', () => {
                 console.log('this is sinon test 1111');
            });
    });
    after( function () {
        testApp.getObj.restore(); // Unwraps the spy
    });
    it('throws errors',function(done) {
         testApp.getObj();
    });
});

Update 2022/01/22

Using sinon's sanbox you could created stub mocks with sandbox.stub() and restores all fakes created through sandbox.restore(), Arjun Malik give an good example

Solution 2

This error is due to not restoring the stub function properly. Use sandbox and then create the stub using the sandbox. After each test inside the suite, restore the sandbox

  beforeEach(() => {
      sandbox = sinon.createSandbox();
      mockObj = sandbox.stub(testApp, 'getObj', fake_function)
  });
  afterEach(() => {
      sandbox.restore();
  });

Solution 3

For cases where you need to restore all the methods of one object, you can use the sinon.restore(obj).

Example:

before(() => {
    userRepositoryMock = sinon.stub(userRepository);
});
after(() => {
    sinon.restore(userRepository);
});

Solution 4

I was also hitting this using the before() and after() hooks of Mocha. I was also using the restore() as mentioned everywhere. Single test file ran fine, multiple did not. Finally found about Mocha root-level-hooks: I did not have my before() and after() inside my own describe(). So it finds all files with before() at the root-level and executes those before starting any tests.

So make sure you have a similar pattern:

describe('my own describe', () => {
  before(() => {
    // setup stub code here
    sinon.stub(myObj, 'myFunc').callsFake(() => {
      return 'bla';
    });
  });
  after(() => {
    myObj.myFunc.restore();
  });
  it('Do some testing now', () => {
    expect(myObj.myFunc()).to.be.equal('bla');
  });
});

Solution 5

Just a heads-up, because this took me about an hour to figure out:

If you have two (or more) test files, and find yourself still getting "already wrapped" error no matter what you try, make sure your beforeEach and afterEach stub / replace handlers are INSIDE the test file's describe block.

If you put them in the global test scope, i.e. OUTSIDE the describe('my test description', () => {}) construct, sinon will attempt it twice and throw this.

Share:
86,973

Related videos on Youtube

Author by

rovy

Updated on January 23, 2022

Comments

  • rovy 10 months

    Though there is a same question here but I could not find answer to my problem so here goes my question:

    I am testing my node js app using mocha and chai. I am using sinion to wrap my function.

    describe('App Functions', function(){
      let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
         //some stuff
      });
      it('get results',function(done) {
         testApp.someFun
      });
    }
    describe('App Errors', function(){
      let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
         //some stuff
      });
      it('throws errors',function(done) {
         testApp.someFun
      });
    }
    

    When I try to run this test it gives me error

    Attempted to wrap getObj which is already wrapped
    

    I also tried putting

    beforeEach(function () {
      sandbox = sinon.sandbox.create();
    });
    afterEach(function () {
      sandbox.restore();
    });
    

    in each describe, but still giving me same error.

    • Nir Alfasi
      Nir Alfasi almost 4 years
      You can find an explanation at the bottom of the post here
  • Ian Robertson
    Ian Robertson almost 6 years
    This didn't work for me when stubbing functions on the object. I had to restore per function like the accepted answer shows.
  • Ashwin Hegde
    Ashwin Hegde over 5 years
    After trying the above accepted way, I am getting the same error under "before all" hook
  • zangw
    zangw over 5 years
    @AshwinHegde, could you please give me your test codes? Maybe I can find some issue here.
  • Matthias Sommer almost 5 years
    sinon.restore() was deprecated in Sinon v2 and removed afterwards. // Previously sinon.restore(stubObject); // Typescript (stubObject as any).restore(); // Javascript stubObject.restore();
  • Luke
    Luke about 4 years
    Is there no way to restore all stubs without specifying each one? Would be great to have a sinon.restoreAll(); that could be run after all tests just to make sure you don't forget to restore a stub.
  • Yegor Zaremba
    Yegor Zaremba over 3 years
    dude, saved my life)
  • Rana Ghosh
    Rana Ghosh over 3 years
    This worked for me. I feel like this should be the accepted answer.
  • Richard
    Richard over 2 years
    I had multiple tests with wrapping functions and need to use afterEach.
  • Edison Spencer
    Edison Spencer over 2 years
    In my case, this was the correct answer, since I was spying a whole object and not a specific method, so I couldn't restore.
  • Sam Arul Raj T about 2 years
    afterEach(()=> { sinon.verifyAndRestore(); });
  • New Alexandria
    New Alexandria 11 months
    highly underrated answer
  • Rubens Mariuzzo
    Rubens Mariuzzo 10 months
    Using sinon's sanbox you could created stub with sandbox.stub(...) and restore everything later with just sandbox.restore()