2016-01-29 7 views
5

Ich kann nicht scheinen setTimeout und clearTimeout in meinen Jasmine Tests auszuspionieren, die durch Karma laufen.Spion auf setTimeout und clearTimeout in Karma und Jasmine

I Variationen über alle diese

spyOn(window, 'setTimeout').and.callFake(()=>{}); 
spyOn(global, 'setTimeout').and.callFake(()=>{}); 
spyOn(window, 'clearTimeout').and.callThrough(); 

clock = jasmine.clock(); 
clock.install(); 
spyOn(clock, 'setTimeout').and.callThrough(); 

runMyCode(); 

expect(window.setTimeout).toHaveBeenCalled(); // no 
expect(global.setTimeout).toHaveBeenCalled(); // nope 
expect(window.clearTimeout).toHaveBeenCalled(); // no again 
expect(clock.setTimeout).toHaveBeenCalled(); // and no 

In jedem Fall versucht haben, kann ich bestätigen, dass setTimeout und clearTimeout haben in runMyCode aufgerufen, sondern immer Expected spy setTimeout to have been called.

Für window, bekomme ich deutlich Das liegt daran, dass der Test und der Runner (das Karma-Fenster) sich in verschiedenen Frames befinden (warum sollte ich etwas anderes erwarten). Aus diesem Grund kann ich keine Bestätigung dafür finden, dass diese globalen Funktionen aufgerufen wurden.

Ich weiß, dass ich jasmine.clock() verwenden kann, um zu bestätigen, dass Timeout/Intervall Callbacks aufgerufen wurden, aber es sieht so aus, als ob ich setTimeout selbst nicht ansehen kann. Und bestätigen, dass clearTimeout einfach aufgerufen wurde, ist nicht möglich.

An dieser Stelle ist das einzige, was ich denken kann, eine separate Abstraktionsschicht zu Wrap setTimeout und clearTimeout hinzuzufügen oder die Funktionen als Abhängigkeiten zu injizieren, was ich vorher getan habe, aber ich denke, ist seltsam.

Antwort

0

Die einzige - und einzige - Lösung, die ich dafür finden konnte, ist Rewire (in meinem Fall muss ich auch Rewire-Webpack verwenden).

Rewire erlaubt es Ihnen, globale Methoden zu ersetzen - aber sobald die Methode ersetzt wurde, kann sie nicht mehr ausspioniert werden. Um also erfolgreich toHaveBeenCalledWith zu verwenden, müssen Sie die Mock-Funktion umschließen und als Proxy verwenden.

var rewire = require('rewire'), 
    myModule = rewire('./path/to/module'); 

describe(function() { 
    var mocks = { 
     setTimeout: function() { return 99: }, 
     clearTimeout: function() {} 
    }; 

    beforeEach(function() { 
     // This will work 
     myModule.__set__('setTimeout', function() { 
      mocks.setTimeout.apply(null, arguments) 
     }) 

     // This will NOT work 
     myModule.__set__('clearTimeout', mocks.clearTimeout) 
    }); 

    it('calls setTimeout', function() { 
     spyOn(mocks, 'setTimeout').and.callThrough(); 
     spyOn(mocks, 'clearTimeout').and.callThrough(); 

     myModule.doSomething(); // this will invoke setTimeout locally 

     expect(mocks.setTimeout).toHaveBeenCalledWith(jasmine.any(Function), 1000); 
     expect(mocks.clearTimeout).toHaveBeenCalledWith(99); // Won't work (see above) 

    }); 
}); 

Natürlich ist dies sicherlich das nächste Mal aufhören zu arbeiten Jasmin, Rewire, Karma, Webpack ... oder das Wetter ... Änderungen (grrr). Wenn dies nicht für Sie funktioniert, hinterlassen Sie bitte einen Kommentar, damit zukünftige Entwickler davon erfahren.

1

Ich war in der Lage, es zu erhalten, wie dies funktioniert:

spyOn(window, 'setTimeout'); 
runMyCode(); 
expect(setTimeout).toHaveBeenCalled(); 

Entfernen Sie einfach das ‚Fenster‘ Objekt aus dem setTimeout Anruf.

Verwandte Themen