2012-02-19 14 views
47

Sto usando Jasmine per verificare se alcuni oggetti sono stati creati e se i metodi sono stati chiamati su di essi.Spiare un costruttore usando Jasmine

Ho un widget jQuery che crea oggetti di flipcounter e chiama il metodo setValue su di essi. Il codice per flipcounter è qui: https://bitbucket.org/cnanney/apple-style-flip-counter/src/13fd00129a41/js/flipcounter.js

I flipcounters vengono creati utilizzando:

var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 

voglio provare che le flipcounters vengono creati e il metodo setValue è chiamato su di loro. Il mio problema è che come faccio a spiare questi oggetti ancor prima che vengano creati? Spio il costruttore e restituisco oggetti falsi? Il codice di esempio sarebbe davvero d'aiuto. Grazie per l'aiuto! :)

Aggiornamento:

Ho provato spiare la flipCounter come questo:

myStub = jasmine.createSpy('myStub'); 
spyOn(window, 'flipCounter').andReturn(myStub); 

//expectation 
expect(window.flipCounter).toHaveBeenCalled(); 

Poi il test per la chiamata setValue da flipCounter:

spyOn(myStub, 'setValue'); 

//expectation 
expect(myStub.setValue).toHaveBeenCalled(); 

la prima test per l'inizializzazione di flipCounter va bene, ma per testare la chiamata setValue, tutto quello che sto ottenendo è un errore 'setValue() non esiste'. Sto facendo questo nel modo giusto? Grazie!

+0

Qual è la ragione che si desidera 'spia' su di esso? –

+1

Voglio assicurarmi che il flipcounter sia stato creato e che sia impostato il valore corretto. – maru

risposta

37

flipCounter è solo un'altra funzione, anche se capita anche di costruire un oggetto. Da qui si può fare:

var cSpy = spyOn(window, 'flipCounter'); 

per ottenere una spia su di esso, e fare ogni sorta di ispezioni su di esso o dire:

var cSpy = spyOn(window, 'flipCounter').andCallThrough(); 
var counter = flipCounter('foo', options); 
expect(cSpy).wasCalled(); 

Tuttavia, questo sembra eccessivo.Sarebbe sufficiente:

var myFlipCounter = new flipCounter("counter", options); 
expect(myFlipCounter).toBeDefined(); 
expect(myFlipCounter.getValue(foo)).toEqual(bar); 
+0

Non spiare una spia del genere non è una buona idea;) Vorrei usare il secondo approccio che ho preso sopra , testare e spiare separatamente su setValue per assicurarsi che funzioni anche. – ggozad

+0

In ogni caso quando si esegue spyOn (finestra, 'flipCounter'). EReturn (myStub); hai sostituito il tuo costruttore con qualcosa che non fa nulla. È necessario chiamareThrough o replicare il costruttore durante il test. – ggozad

+0

Se TUTTO quello che si vuole fare è controllare che sia stato chiamato setValue, non spiare il costruttore. Piuttosto spia (e callThrough()) su setValue. È quindi possibile controllare che sia stato chiamato, controllarne gli argomenti e avere ancora l'oggetto. – ggozad

-2

Non so come farlo usando i jasmine mock, ma se volete potenti mocking/spy/stub raccomando sinon.js, che funziona molto bene con il gelsomino.

Da docs:

Una spia di prova è una funzione che registra argomenti, valore di ritorno, il valore di questo e di eccezione generata (se presente) per tutti i suoi appelli. Una spia può essere una funzione anonima o può avvolgere una funzione esistente.

I mock (e le aspettative finte) sono metodi falsi (come le spie) con il comportamento pre-programmato (come gli stub) nonché le aspettative pre-programmate . Un mock fallirà il test se non viene utilizzato come previsto.

Con sinon.js è possibile creare una finta del costruttore flipCounter che restituisce un'altra spia.

Quindi asserire che il costruttore è stato chiamato utilizzando constructorMock.calledWithNew() e asserire che la spia restituita è stata chiamata con returnSpy.calledWith (arg1, arg2 ...).

+4

Non c'è bisogno di usare una libreria extra quando Jasmine ha dei mock capaci integrati. Sinon.js è utile per altre cose anche se – sMoZely

3

Quanto segue non si basa su "finestra". Consente di dire che questo è il codice che si desidera testare -

function startCountingFlips(flipCounter) { 
    var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
} 

Il test potrebbe essere -

var initSpy = jasmine.createSpy('initFlipCounter'); 
var flipCounter = function(id, options) { 
    initSpy(id, options); 
} 
startCountingFlips(flipCounter); 
expect(initSpy).toHaveBeenCalledWith("counter", {inc:23, pace:500}); 
4

Bisogna implementare un costruttore falso per flipCounter che imposta la proprietà setValue a una funzione spia. Diciamo che la funzione che si desidera verificare è questo:

function flipIt() { 
    var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
    myFlipCounter.setValue(100); 
} 

tuo spec dovrebbe essere simile a questo:

describe('flipIt', function() { 
    var setValue; 
    beforeEach(function() { 
    setValue = jasmine.createSpy('setValue'); 
    spyOn(window, 'flipCounter').and.callFake(function() { 
     this.setValue = setValue; 
    }); 
    flipIt(); 
    }); 
    it('should call flipCounter constructor', function() { 
    expect(window.flipCounter) 
     .toHaveBeenCalledWith("counter", {inc: 23, pace: 500}); 
    }); 
    it('should call flipCounter.setValue', function() { 
    expect(setValue).toHaveBeenCalledWith(100); 
    }); 
}); 
10

Io suggerirei di usare jasmine.createSpyObj() quando si vuole prendere in giro oggetti con proprietà che hanno bisogno di essere spiati sopra.

myStub = jasmine.createSpyObj('myStub', ['setValue']); 
spyOn(window, 'flipCounter').andReturn(myStub); 

Questo mette alla prova le interazioni con l'interfaccia di flipCounter previsto, senza dipendere dal flipCounter attuazione.

+1

Preferisco questa risposta sulla risposta di @ ggozad, perché mantiene isolati i moduli esterni dai test e utilizza un'utilità gelsomino incorporata progettata specificamente per la simulazione di oggetti di tipo istanza. –

0

La mia versione di testare un costruttore è quello di spiare sul prototipo:

spyOn(flipCounter.prototype, 'setValue').and.callThrough(); 
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
expect(flipCounter.prototype.setValue).toHaveBeenCalledTimes(1); 
+0

Bello, grazie. Anche questo funziona perfettamente con oggetti built-in come 'XMLHttpRequest' –

+0

Per ajax mockup io uso questo: https://jasmine.github.io/2.2/ajax.html – Holger

Problemi correlati