Sinon Stubs leicht reinigen


134

Gibt es eine Möglichkeit, alle Verspottungen und Stubs von Sinon-Spionen, die mit Mokkas vor jedem Block sauber funktionieren, einfach zurückzusetzen?

Ich sehe, dass Sandboxing eine Option ist, aber ich sehe nicht, wie Sie eine Sandbox dafür verwenden können

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

Antworten:


304

Sinon bietet diese Funktionalität durch die Verwendung von Sandboxen , die auf verschiedene Arten verwendet werden können:

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

oder

// 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 Wenn Sie asynchrone Tests haben, müssen Sie die erste Methode verwenden, andernfalls bereinigt sinon die Stubs, bevor die Ausführung Ihres Tests abgeschlossen ist.
Keithjgrant

3
Wenn Sie sinon> 5.0 verwenden, lesen Sie unten. Es gibt jetzt eine viel einfachere Methode: stackoverflow.com/a/55251560/4464702
RAnders00

53

Frühere Antworten schlagen vor sandboxes, dies zu verwenden, aber gemäß der Dokumentation :

Seit sinon@5.0.0 ist das sinon-Objekt eine Standard-Sandbox.

Das bedeutet, dass das Aufräumen Ihrer Stubs / Mocks / Spione jetzt so einfach ist wie:

var sinon = require('sinon');

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

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

10
Dies ist die beste Antwort für alle, die dies nach April 2018 lesen.
Nick Cox

1
noch neeter: afterEach (sinon.restore)
Benjam

Ich denke, das ist besser, weil explizite Sandboxen unnötige Komplexität verursachen. Benötigen Sie wirklich mehrere separate Sandkästen mit unterschiedlichen Verspottungen desselben Objekts? Wahrscheinlich nicht.
Gherman

13

Ein Update auf @keithjgrant Antwort.

Ab Version v2.0.0 wurde die Methode sinon.test in ein separates sinon-testModul verschoben . Damit die alten Tests bestanden werden, müssen Sie diese zusätzliche Abhängigkeit in jedem Test konfigurieren:

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

Alternativ haben Sie ohne sinon-testund Nutzung Sandkästen :

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
Oder Sie können einfach das Sinon-Test-Paket verwenden und Ihren Code wie zuvor fortsetzen :-D
Oligofren

10

Sie können sinon.collection verwenden, wie in diesem Blog-Beitrag (vom Mai 2010) des Autors der sinon-Bibliothek dargestellt.

Die sinon.collection-API hat sich geändert und kann folgendermaßen verwendet werden:

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()stellt nur das Verhalten der Stubbed-Funktionalität wieder her, setzt jedoch den Status der Stubs nicht zurück. Sie müssen Ihre Tests entweder mit den Stubs abschließen sinon.testund sie verwenden this.stuboder sie einzeln aufrufenreset()


6

Wenn Sie ein Setup wünschen, bei dem sinon immer für alle Tests zurückgesetzt wird:

in helper.js:

import sinon from 'sinon'

var sandbox;

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

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

Dann in Ihrem Test:

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

3

Beachten Sie, dass Sie bei Verwendung von qunit anstelle von Mokka diese in ein Modul einschließen müssen, z

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 wechselt zu beforeEachund afterEach. Die Methoden setupund teardownwerden nicht mehr unterstützt.
Kevin Bullaughey

0

Erstellen Sie eine Sandbox, die als Blackbox-Container für alle Ihre Spione, Stubs, Mocks und Fakes fungiert.

Alles, was Sie tun müssen, ist, im allerersten Beschreibungsblock eine Sandbox zu erstellen, damit Sie in allen Testfällen darauf zugreifen können. Und wenn Sie mit allen Testfällen fertig sind, sollten Sie die ursprünglichen Methoden freigeben und die Stubs mithilfe der Methode sandbox.restore()im afterEach-Hook bereinigen, damit zur Laufzeit freigegebene Ressourcen freigegeben werden. Der afterEachTestfall ist bestanden oder fehlgeschlagen.

Hier ist ein Beispiel:

 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(); 
    });
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.