Łatwe czyszczenie zacisków sinonowych


134

Czy istnieje sposób, aby łatwo zresetować wszystkie kpiny i kikuty szpiegów Sinon, które będą działać czysto z mokką przed każdym blokiem.

Widzę, że piaskownica jest opcją, ale nie widzę, jak można do tego użyć piaskownicy

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

Odpowiedzi:


304

Sinon zapewnia tę funkcjonalność poprzez użycie piaskownic , z których można korzystać na kilka sposobów:

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

lub

// 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 Kiedy masz testy asynchroniczne, musisz użyć pierwszej metody, w przeciwnym razie sinon wyczyści jego kody pośredniczące przed zakończeniem wykonywania testu.
keithjgrant

3
Jeśli używasz sinon> 5.0, przeczytaj poniżej. Jest teraz znacznie łatwiejsza metoda: stackoverflow.com/a/55251560/4464702
RAnders00

53

Poprzednie odpowiedzi sugerują użycie sandboxesdo tego celu, ale zgodnie z dokumentacją :

Ponieważ sinon@5.0.0, obiekt sinon jest domyślną piaskownicą.

Oznacza to, że oczyszczenie twoich stubów / udawanych szpiegów jest teraz tak proste, jak:

var sinon = require('sinon');

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

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

10
To najlepsza odpowiedź dla każdego, kto to czyta po kwietniu 2018 r.
Nick Cox

1
nawet neeter: afterEach (sinon.restore)
Benjam

Myślę, że jest to lepsze, ponieważ jawne piaskownice powodują niepotrzebną złożoność. Czy naprawdę będziesz potrzebować kilku oddzielnych piaskownic z różnymi makietami tego samego obiektu? Prawdopodobnie nie.
Gherman

13

Aktualizacja odpowiedzi @keithjgrant.

Z wersji v2.0.0 kolejnych, sinon.test metoda została przeniesiona do oddzielnego sinon-testmodułu . Aby stare testy przeszły pomyślnie, musisz skonfigurować tę dodatkową zależność w każdym teście:

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

Alternatywnie możesz obejść się bez piaskownicsinon-test i używać ich :

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
Lub możesz po prostu użyć pakietu sinon-test i kontynuować kod jak poprzednio :-D
oligofren

10

Możesz użyć sinon.collection, jak pokazano w tej poście na blogu (z maja 2010) autorstwa autora biblioteki sinon.

Interfejs API sinon.collection uległ zmianie i sposób jego użycia jest następujący:

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()po prostu przywraca zachowanie funkcji skrótów, ale nie resetuje stanu kodów pośredniczących. Będziesz musiał albo opakować swoje testy sinon.testi użyć, this.stubalbo indywidualnie wywołać reset()kody pośredniczące


6

Jeśli chcesz, aby konfiguracja, która będzie miała sinon, zawsze resetuje się dla wszystkich testów:

w helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Następnie w swoim teście:

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

3

Zauważ, że używając qunit zamiast mokki, musisz owinąć je w moduł, np

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 przełącza się na beforeEachi afterEach. setupI teardownmetody będą przestarzałe.
Kevin Bullaughey

0

Stwórz piaskownicę, która będzie działać jako pojemnik z czarną skrzynką dla wszystkich twoich szpiegów, stubów, fałszywek i podróbek.

Wszystko, co musisz zrobić, to utworzyć piaskownicę w pierwszym bloku opisu, aby była dostępna we wszystkich przypadkach testowych. A kiedy skończysz ze wszystkimi przypadkami testowymi, powinieneś zwolnić oryginalne metody i wyczyścić sandbox.restore()kody pośredniczące za pomocą metody w podpięciu afterEach, aby w czasie wykonywania zwolnić zatrzymane zasobyafterEach Przypadek testowy przeszedł pomyślnie lub zakończył się niepowodzeniem.

Oto przykład:

 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(); 
    });
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.