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.