Pulire facilmente i mozziconi di Sinon


135

C'è un modo per ripristinare facilmente tutti i mock e gli stub degli spys sinon che funzioneranno in modo pulito con i moka prima di ogni blocco.

Vedo sandboxing è un'opzione ma non vedo come è possibile utilizzare un sandbox per questo

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

Risposte:


304

Sinon fornisce questa funzionalità tramite l'uso di Sandbox , che possono essere utilizzati in due modi:

// 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"
}

o

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

6
@CamJackson Quando hai i test asincroni, devi usare il primo metodo, altrimenti sinon pulisce i suoi stub prima che il test abbia terminato l'esecuzione.
— keithjgrant,

3
Se stai usando sinon> 5.0 leggi sotto. C'è ora un metodo molto più semplice: stackoverflow.com/a/55251560/4464702
— RAnders00

54

Le risposte precedenti suggeriscono di utilizzare sandboxesper ottenere questo risultato, ma secondo la documentazione :

Da sinon@5.0.0, l'oggetto sinon è un sandbox predefinito.

Ciò significa che ripulire i tuoi mozziconi / beffe / spie ora è facile come:

var sinon = require('sinon');

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

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

10
Questa è la risposta migliore per chiunque legga questo dopo aprile 2018.
— Nick Cox,

1
anche neeter: afterEach (sinon.restore)
— Benjam

Penso che sia meglio perché sandbox esplicite creano complessità inutili. Avrai davvero bisogno di più sandbox separate con diverse beffe dello stesso oggetto? Probabilmente no.
— Gherman

13

Un aggiornamento alla risposta di @keithjgrant.

Dalla versione v2.0.0 in poi, il metodo sinon.test è stato spostato in un sinon-testmodulo separato . Per superare i vecchi test è necessario configurare questa dipendenza aggiuntiva in ciascun test:

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

In alternativa, fai a meno sinon-teste usi i 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"
} 

1
Oppure puoi semplicemente usare il pacchetto sinon-test e continuare il tuo codice come prima :-D
— oligofren

10

Puoi usare sinon.collection come illustrato in questo post del blog (datato maggio 2010) dall'autore della libreria sinon.

L'api sinon.collection è cambiato e un modo per usarlo è il seguente:

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

6

restore()ripristina solo il comportamento della funzionalità stub ma non ripristina lo stato degli stub. Dovrai o avvolgere i test con sinon.teste utilizzare this.stubo chiamare individualmente reset()sugli stub


6

Se si desidera un'installazione che avrà sinon sempre ripristinarsi per tutti i test:

in helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Quindi, nel tuo test:

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

3

Si noti che quando si utilizza qunit invece di moka, è necessario avvolgerli in un modulo, ad es

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

3
qunit 2 sta passando a beforeEache afterEach. I metodi setupe teardownsaranno deprecati.
— Kevin Bullaughey,

0

Crea una sandbox che fungerà da contenitore di una scatola nera per tutte le tue spie, tronconi, beffe e falsi.

Tutto quello che devi fare è creare un sandbox nel primo blocco descrittivo in modo che sia accessibile in tutti i casi di test. E una volta sandbox.restore()terminati tutti i casi di test, è necessario rilasciare i metodi originali e ripulire gli stub utilizzando il metodo nell'hook afterEach in modo che durante l'esecuzione rilasci il afterEachcaso di test delle risorse trattenute venga superato o fallito.

Ecco un esempio:

 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(); 
    });
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.