web-dev-qa-db-fra.com

Sinon erreur Tentative d’emballer une fonction déjà encapsulée

Bien qu'il y ait une même question ici mais je ne pouvais pas trouver de réponse à mon problème alors voici ma question: 

Je teste mon application js noeud en utilisant moka et chai. J'utilise sinion pour envelopper ma fonction. 

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
  });
}

Quand j'essaye de lancer ce test, ça me donne une erreur 

Attempted to wrap getDbObj which is already wrapped

J'ai aussi essayé de mettre 

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

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

dans chaque décrire, mais en me donnant toujours la même erreur. 

50
Rohit Vyavahare

Vous devez restaurer la fonction getObj in after(). Veuillez l’essayer comme ci-dessous.

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();
    });
});
67
zangw

Dans les cas où vous devez restaurer toutes les méthodes d'un objet, vous pouvez utiliser la fonction sinon.restore(obj)

Exemple:

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

after(() => {
    sinon.restore(userRepository);
});
8
Renan Ferreira

Je frappais également ceci en utilisant les crochets de moka d'avant () et d'après (). J'utilisais aussi le restore () comme mentionné partout. Un seul fichier de test fonctionnait bien, plusieurs non. Enfin trouvé à propos de Moka root-level-hooks : Je n'avais pas mon avant () et après () à l'intérieur de mon propre describe (). Donc, il trouve tous les fichiers avec before () au niveau racine et les exécute avant de commencer les tests.

Donc, assurez-vous que vous avez un modèle similaire:

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');
  });
});
5
Wilfred Dittmer

Il est conseillé d'initialiser les stubs dans "beforeEach" et de les restaurer dans "afterEach". Mais si vous vous sentez aventureux, voici ce qui suit.

describe('App Functions', function(){

  let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
     //some stuff
  });
  it('get results',function(done) {
     testApp.someFun
     mockObj .restore();
  });
}

describe('App Errors', function(){

  let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
     //some stuff
  });
  it('throws errors',function(done) {
     testApp.someFun
     mockObj .restore();
  });
}
2
Karna

Cette erreur est due à la restauration incorrecte de la fonction de stub. Utilisez le bac à sable, puis créez le stub à l'aide du bac à sable. Après la suite de tests, restaurez le bac à sable.

  before(() => {
      sandbox         = sinon.sandbox.create();
      mockObj         = sandbox.stub(testApp, 'getObj', fake_function)
  });
  after(() => {
      sandbox.restore();
  });
0
Arjun Malik

Même avec le bac à sable, cela pourrait vous donner l'erreur. Surtout lorsque les tests sont exécutés en parallèle pour les classes ES6.

const sb = sandbox.create();

before(() => {
  sb.stub(MyObj.prototype, 'myFunc').callsFake(() => {
    return 'whatever';
  });
});
after(() => {
  sb.restore();
});

cela pourrait générer la même erreur si un autre test tente de remplacer myFunc du prototype. J'ai pu résoudre ce problème mais je n'en suis pas fier ...

const sb = sandbox.create();

before(() => {
  MyObj.prototype.myFunc = sb.stub().callsFake(() => {
    return 'whatever';
  });
});
after(() => {
  sb.restore();
});
0
Tonino

Je suis tombé dessus avec des espions. Ce comportement rend sinon assez difficile de travailler avec. J'ai créé une fonction d'assistance qui tente de supprimer tout espion existant avant d'en créer un nouveau. De cette façon, je n'ai pas à m'inquiéter d'aucun état avant/après. Une approche similaire pourrait également fonctionner pour les talons.

import sinon, { SinonSpy } from 'sinon';

/**
 * When you set a spy on a method that already had one set in a previous test,
 * sinon throws an "Attempted to wrap [function] which is already wrapped" error
 * rather than replacing the existing spy. This helper function does exactly that.
 *
 * @param {object} obj
 * @param {string} method
 */
export const spy = function spy<T>(obj: T, method: keyof T): SinonSpy {
  // try to remove any existing spy in case it exists
  try {
    // @ts-ignore
    obj[method].restore();
  } catch (e) {
    // noop
  }
  return sinon.spy(obj, method);
};
0
Phil