2016-01-29 14 views
5

Non riesco a essere in grado di spiare setTimeout e clearTimeout nei miei test di Jasmine, che vengono eseguiti attraverso Karma.Spia su setTimeout e clearTimeout in Karma e Jasmine

ho provato variazioni su tutto questo

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 ogni caso, posso confermare che setTimeout e clearTimeout sono state invocate nel runMyCode, ma invece ho sempre ottenere Expected spy setTimeout to have been called.

Per window, chiaramente questo perché il test e il runner (la finestra di Karma) sono in frame diversi (quindi perché dovrei aspettarmi qualcosa di diverso). Ma a causa di ciò, non vedo alcun modo per confermare che queste funzioni globali siano state invocate.

So che posso usare jasmine.clock() per confermare che i callback di intervallo/intervallo siano stati richiamati, ma sembra che non riesca a guardare lo stesso setTimeout. E confermare che clearTimeout è stato chiamato semplicemente non è possibile.

A questo punto, l'unica cosa che mi viene in mente è quello di aggiungere uno strato separato di astrazione per avvolgere setTimeout e clearTimeout o per iniettare le funzioni come dipendenze, che ho fatto prima, ma penso che è strano.

risposta

0

L'unica - e unica - soluzione che ho trovato per questo è usare Rewire (nel mio caso, mi viene richiesto anche di usare Rewire-Webpack).

Rewire consente di sostituire i metodi globali, ma una volta che il metodo è stato sostituito, non può essere spiato. Pertanto, per utilizzare correttamente lo toHaveBeenCalledWith, è necessario eseguire il wrapping e il proxy della funzione di simulazione.

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) 

    }); 
}); 

Naturalmente, questo sarà sicuramente fermata di lavoro la prossima volta Jasmine, Rewire, Karma, Webpack ... o il tempo ... cambiamenti (grrr). Se questo non funziona per te, ti preghiamo di lasciare un commento in modo che i futuri sviluppatori lo sappiano.

1

sono stato in grado di farlo funzionare in questo modo:

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

è sufficiente rimuovere l'oggetto 'finestra' dalla chiamata setTimeout.

Problemi correlati