Limpiar trozos de sinón fácilmente


135

¿Hay alguna manera de restablecer fácilmente todos los simulacros y trozos de sinon spys que funcionarán limpiamente con los mocas antes de cada bloque?

Veo que el sandboxing es una opción, pero no veo cómo puedes usar un sandbox para esto

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

Respuestas:


304

Sinon proporciona esta funcionalidad mediante el uso de Sandboxes , que se pueden usar de dos maneras:

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

66
@CamJackson Cuando tienes pruebas asíncronas, necesitas usar el primer método, de lo contrario, Sinon limpia sus stubs antes de que tu prueba haya terminado de ejecutarse.
keithjgrant

3
Si está utilizando sinon> 5.0, lea a continuación. Ahora hay un método mucho más fácil: stackoverflow.com/a/55251560/4464702
RAnders00

54

Las respuestas anteriores sugieren usar sandboxespara lograr esto, pero de acuerdo con la documentación :

Desde sinon@5.0.0, el objeto sinon es un sandbox predeterminado.

Eso significa que limpiar sus trozos / simulacros / espías ahora es tan fácil como:

var sinon = require('sinon');

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

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

10
Esta es la mejor respuesta para cualquiera que lea esto después de abril de 2018.
Nick Cox

1
incluso más libre: afterEach (sinon.restore)
Benjam

Creo que esto es mejor porque los sandboxes explícitos crean una complejidad innecesaria. ¿Realmente vas a necesitar varias cajas de arena separadas con diferentes simulacros del mismo objeto? Probablemente no.
Gherman

13

Una actualización de la respuesta @keithjgrant.

Desde la versión v2.0.0 en adelante, el método sinon.test se ha movido a un sinon-testmódulo separado . Para pasar las pruebas anteriores, debe configurar esta dependencia adicional en cada prueba:

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

Alternativamente, puedes prescindir sinon-testy usar sandboxes :

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
O simplemente puede usar el paquete sinon-test y continuar su código como antes :-D
oligofren

10

Puede usar sinon.collection como se ilustra en esta publicación de blog (fechada en mayo de 2010) por el autor de la biblioteca de sinon.

La API de sinon.collection ha cambiado y una forma de usarla es la siguiente:

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()solo restaura el comportamiento de la funcionalidad de stubbed pero no restablece el estado de los stubs. Tendrá que completar sus pruebas sinon.testy usarlas this.stubo llamar individualmente reset()a los talones


6

Si desea una configuración que tendrá sinon, siempre se reiniciará para todas las pruebas:

en helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Luego, en tu prueba:

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

3

Tenga en cuenta que cuando use qunit en lugar de mocha, debe envolverlos en un módulo, por ejemplo

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 está cambiando a beforeEachy afterEach. Los métodos setupy teardownquedarán en desuso.
Kevin Bullaughey

0

Cree una caja de arena que actuará como un contenedor de caja negra para todos sus espías, trozos, simulacros y falsificaciones.

Todo lo que tiene que hacer es crear un sandbox en el primer bloque de descripción para que sea accesible en todos los casos de prueba. Y una vez que haya terminado con todos los casos de prueba, debe liberar los métodos originales y limpiar los apéndices utilizando el método sandbox.restore()en el gancho afterEach para que en tiempo de ejecución libere el afterEachcaso de prueba de recursos retenidos que se pasa o falla.

Aquí hay un ejemplo:

 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(); 
    });
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.