Limpando facilmente stubs sinon


134

Existe uma maneira de redefinir facilmente todas as zombarias e stubs de sinon spys que funcionarão corretamente com os blocos beforeEach de mocha.

Vejo que o sandbox é uma opção, mas não vejo como você pode usar um sandbox para esse

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

Respostas:


304

O Sinon fornece essa funcionalidade através do uso de Sandboxes , que podem ser usadas de duas maneiras:

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

6
@CamJackson Quando você tem testes assíncronos, precisa usar o primeiro método; caso contrário, o sinon limpa seus stubs antes que seu teste seja executado.
keithjgrant

3
Se você estiver usando sinon> 5.0, leia abaixo. Há agora um método muito mais fácil: stackoverflow.com/a/55251560/4464702
RAnders00

53

As respostas anteriores sugerem o uso sandboxespara fazer isso, mas de acordo com a documentação :

Desde sinon@5.0.0, o objeto sinon é uma sandbox padrão.

Isso significa que limpar seus stubs / zombarias / espiões agora é tão fácil quanto:

var sinon = require('sinon');

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

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

10
Esta é a melhor resposta para quem lê este depois de Abril de 2018.
Nick Cox

1
ainda neeter: afterEach (sinon.restore)
Benjam

Eu acho que isso é melhor porque caixas de areia explícitas criam complexidade desnecessária. Você realmente precisará de várias caixas de areia separadas com zombarias diferentes do mesmo objeto? Provavelmente não.
Gherman

13

Uma atualização para a resposta @keithjgrant.

A partir da versão v2.0.0 , o método sinon.test foi movido para um sinon-testmódulo separado . Para fazer os testes antigos passarem, você precisa configurar essa dependência extra em cada teste:

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

Como alternativa, você fica sem sinon-teste usa 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
Ou você pode simplesmente realmente usar o pacote sinon-teste e continuar o seu código como antes :-D
oligofren

10

Você pode usar sinon.collection conforme ilustrado nesta postagem do blog (datada de maio de 2010) pelo autor da biblioteca sinon.

A API do sinon.collection mudou e uma maneira de usá-la é a seguinte:

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()apenas restaura o comportamento da funcionalidade stubbed, mas não redefine o estado dos stubs. Você precisará encerrar seus testes sinon.teste usar this.stubou chamar individualmente reset()os stubs


6

Se você deseja uma configuração que terá o sinon sempre se redefinirá para todos os testes:

em helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Então, no seu teste:

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

3

Observe que ao usar o qunit em vez do mocha, é necessário envolvê-los em um módulo, por exemplo

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
o qunit 2 está mudando para beforeEache afterEach. Os métodos setupe teardownserão descontinuados.
precisa saber é o seguinte

0

Crie uma caixa de areia que funcionará como um recipiente de caixa preta para todos os seus espiões, tocos, zombarias e falsificações.

Tudo o que você precisa fazer é criar uma caixa de proteção no primeiro bloco de descrição, para que seja acessível em todos os casos de teste. E quando terminar todos os casos de teste, você deverá liberar os métodos originais e limpar os stubs usando o método sandbox.restore()no gancho afterEach, para que, em tempo de execução, libere recursos retidosafterEach caso de teste é aprovado ou falhou.

Aqui está um exemplo:

 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(); 
    });
});
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.