Nettoyer facilement les stubs sinon

135

Existe-t-il un moyen de réinitialiser facilement tous les mocks et stubs sinon spys qui fonctionneront proprement avec les blocs beforeEach de moka.

Je vois que le sandbox est une option mais je ne vois pas comment vous pouvez utiliser un sandbox pour cela

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
Austinbv
la source

Réponses:

304

Sinon fournit cette fonctionnalité grâce à l'utilisation de sandbox , qui peuvent être utilisées de plusieurs manières:

// manually create and restore the sandbox
var sandbox;
beforeEach(function () {
    sandbox = sinon.sandbox.create();
});

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

it('should restore all mocks stubs and spies between tests', function() {
    sandbox.stub(some, 'method'); // note the use of "sandbox"
}

ou

// wrap your test function in sinon.test()
it("should automatically restore all mocks stubs and spies", sinon.test(function() {
    this.stub(some, 'method'); // note the use of "this"
}));
Keithjgrant
la source
6
@CamJackson Lorsque vous avez des tests asynchrones, vous devez utiliser la première méthode, sinon sinon nettoie ses stubs avant la fin de l'exécution de votre test.
keithjgrant
3
Si vous utilisez sinon> 5.0, lisez ci-dessous. Il existe maintenant une méthode beaucoup plus simple: stackoverflow.com/a/55251560/4464702
RAnders00
54

Les réponses précédentes suggèrent d'utiliser sandboxespour accomplir cela, mais selon la documentation :

Depuis [email protected], l'objet sinon est un sandbox par défaut.

Cela signifie que nettoyer vos talons / mocks / espions est désormais aussi simple que:

var sinon = require('sinon');

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

afterEach(function () {
    sinon.restore();
});
Myk Willis
la source
10
C'est la meilleure réponse pour tous ceux qui liront ceci après avril 2018.
Nick Cox
1
even neeter: afterEach (sinon.restore)
Benjam
Je pense que c'est mieux car les bacs à sable explicites créent une complexité inutile. Allez-vous vraiment avoir besoin de plusieurs bacs à sable séparés avec différentes simulations du même objet? Probablement pas.
Gherman
13

Une mise à jour de la réponse @keithjgrant.

Depuis la version v2.0.0 , la méthode sinon.test a été déplacée vers un sinon-testmodule séparé . Pour que les anciens tests réussissent, vous devez configurer cette dépendance supplémentaire dans chaque test:

var sinonTest = require('sinon-test');
sinon.test = sinonTest.configureTest(sinon);

Vous pouvez également vous en passer sinon-testet utiliser des sandbox :

var sandbox = sinon.sandbox.create();

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

it('should restore all mocks stubs and spies between tests', function() {
    sandbox.stub(some, 'method'); // note the use of "sandbox"
} 
anand
la source
1
Ou vous pouvez simplement utiliser le package sinon-test et continuer votre code comme avant :-D
oligofren
10

Vous pouvez utiliser sinon.collection comme illustré dans ce billet de blog (daté de mai 2010) par l'auteur de la bibliothèque sinon.

L'API sinon.collection a changé et une façon de l'utiliser est la suivante:

beforeEach(function () {
  fakes = sinon.collection;
});

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

it('should restore all mocks stubs and spies between tests', function() {
  stub = fakes.stub(window, 'someFunction');
}
Dimitris Zorbas
la source
6

restore()restaure simplement le comportement de la fonctionnalité stubbed mais ne réinitialise pas l'état des stubs. Vous devrez soit encapsuler vos tests avec sinon.testet utiliser, this.stubsoit appeler individuellement reset()les stubs

Sandeep Adi
la source
6

Si vous voulez une configuration qui devra sinon toujours se réinitialiser pour tous les tests:

dans helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Ensuite, dans votre test:

it("some test", function() {
    this.sinon.stub(obj, 'hi').returns(null)
})
sethcall
la source
3

Notez que lorsque vous utilisez qunit au lieu de mocha, vous devez les envelopper dans un module, par exemple

module("module name"
{
    //For QUnit2 use
    beforeEach: function() {
    //For QUnit1 use
    setup: function () {
      fakes = sinon.collection;
    },

    //For QUnit2 use
    afterEach: function() {
    //For QUnit1 use
    teardown: function () {
      fakes.restore();
    }
});

test("should restore all mocks stubs and spies between tests", function() {
      stub = fakes.stub(window, 'someFunction');
    }
);
sfuqua
la source
3
qunit 2 passe à beforeEachet afterEach. Les méthodes setupet teardownseront obsolètes.
Kevin Bullaughey
0

Créez un bac à sable qui agira comme un conteneur de boîte noire pour tous vos espions, talons, moqueries et faux.

Tout ce que vous avez à faire est de créer un bac à sable dans le tout premier bloc de description afin qu'il soit accessible dans tous les cas de test. Et une fois que vous avez terminé avec tous les cas de test, vous devez publier les méthodes d'origine et nettoyer les stubs à l'aide de la méthode sandbox.restore()du hook afterEach afin qu'au moment de l'exécution, il libère le afterEachcas de test des ressources bloquées soit réussi ou échoué.

Voici un exemple:

 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(); 
    });
});
kavigun
la source