2015-07-12 18 views
16

Ho una funzioneJasmine - come spyOn metodi di istanza

var data = {}; 
var myFunc = function() { 
    data.stuff = new ClassName().doA().doB().doC(); 
}; 

mi piacerebbe provare che doA, doB e doC sono stati tutti chiamati.

Ho provato spiare i metodi di istanza come questo

beforeEach(function() { 
    spyOn(ClassName, 'doA'); 
}; 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.doA)toHaveBeenCalled(); 
}); 

ma che appena mi dà un "metodo DOA() non esiste" errore.

Qualche idea?

+0

C'è una grande differenza tra '' ClassName.doA' e ClassName.doA() '. – bardzusny

risposta

24

Il punto in cui hai sbagliato è stata la tua comprensione di come fare riferimento ai metodi in JavaScript in un contesto statico. Quello che sta facendo il tuo codice è spiare ClassName.doA (ovvero la funzione collegata al costruttore ClassName come la proprietà doA, che non è quello che vuoi).

Se si desidera rilevare quando quel metodo viene chiamato su qualsiasi istanza di ClassName ovunque, è necessario spiare il prototipo.

beforeEach(function() { 
    spyOn(ClassName.prototype, 'doA'); 
}); 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.prototype.doA).toHaveBeenCalled(); 
}); 

Naturalmente, questo presuppone che doA vive nella catena di prototipi. Se si tratta di una proprietà propria, non esiste alcuna tecnica che è possibile utilizzare senza poter fare riferimento all'oggetto anonimo in myFunc. Se avessi accesso all'istanza ClassName all'interno di myFunc, sarebbe l'ideale, dal momento che potresti semplicemente fare spyOn direttamente.

P.S. Dovresti davvero mettere "Jasmine" nel titolo.

+0

Siamo di fronte a una sfida simile, in cui viene attivato il metodo 'ClassName.prototype.doA', ma i campi di istanza non vengono istanziati all'interno di un'istanza di' ClassName'. I campi di istanza sono popolati nel costruttore, ma sfortunatamente sono tutti indefiniti quando stiamo spiando uno dei metodi di istanza. –

+0

Wow, ottima risposta. Ho sempre usato https://github.com/mfncooper/mockery per deridere l'intero costruttore nella cache del modulo richiesto. Non solo è più prolisso, a volte porta a test che hanno davvero difficoltà a risolvere i problemi di \ debug. Questa è una grande soluzione che è molto più facile da capire. Jasmine dovrebbe davvero includere questo esempio nei loro documenti. – Eric

5

Facciamo un po 'di refactoring del codice come vogliamo implementare costruttore iniezione modello come afferma James Shore che:

Dependency Injection significa dare un oggetto le proprie variabili di istanza. Veramente. Questo è tutto.

var data = {}; 
var stuff = new ClassName() 

var myFunc = function(stuff) { // move step of creation new object outside 
    data.stuff = stuff.doA().doB().doC(); 
}; 

E il tempo per alcuni test

function ClassName() { 
 
} 
 

 
var data = {}; 
 
var stuff = new ClassName() 
 

 
var myFunc = function(stuff) { 
 
    data.stuff = stuff.doA().doB().doC(); 
 
}; 
 

 

 
describe('stub for ClassName implementation', function() { 
 
    var stubStuff = { 
 
    doA: function() { 
 
     return stubStuff 
 
    }, 
 
    doB: function() { 
 
     return stubStuff 
 
    }, 
 
    doC: function() { 
 
     return stubStuff 
 
    } 
 
    } 
 

 
    beforeEach(function() { 
 
    spyOn(stubStuff, 'doA').and.callThrough(); 
 
    }); 
 

 
    it('calls "doA" on "myFunc" exection', function() { 
 
    myFunc(stubStuff); 
 
    expect(stubStuff.doA).toHaveBeenCalled(); 
 
    }); 
 
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" /> 
 
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>

Problemi correlati