2015-07-12 16 views
16

Mam funkcjiJasmine - jak spyOn metody instancji

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

chciałbym przetestować że doA, doB i doC zostali wezwani.

Próbowałem szpiegostwo na metodach przykład jak ten

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

ale to po prostu daje mi „metody DOA() nie istnieje” błąd.

Wszelkie pomysły?

+0

Istnieje zasadnicza różnica pomiędzy 'ClassName.doA' i' ClassName.doA() '. – bardzusny

Odpowiedz

24

Nie do końca zrozumiałe jest, jak rozumieć metody w JavaScript w kontekście statycznym. To, co faktycznie robi twój kod, to szpiegowanie ClassName.doA (tj. Funkcja dołączona do konstruktora ClassName jako właściwości doA, co nie jest tym, czego potrzebujesz).

Jeśli chcesz wykryć, kiedy ta metoda zostanie wywołana w dowolnym wystąpieniu ClassName w dowolnym miejscu, musisz sprawdzić prototyp.

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

Oczywiście, to zakładając, że doA życie w łańcuchu prototypów. Jeśli jest to własność własna, nie ma techniki, której można użyć bez możliwości odwoływania się do anonimowego obiektu w myFunc. Gdybyś miał dostęp do instancji ClassName wewnątrz myFunc, byłby idealny, ponieważ mógłbyś tylko bezpośrednio wycenić ten obiekt na spyOn.

P.S. Powinieneś naprawdę umieścić "Jasmine" w tytule.

+0

Mamy do czynienia z podobnym wyzwaniem, w którym metoda 'ClassName.prototype.doA' jest uruchamiana, ale pola instancji nie są tworzone w instancji klasy" ClassName ". Pola instancji są zapełniane w konstruktorze, ale niestety wszystkie są niezdefiniowane, gdy szpiegujemy jedną z metod instancji. –

+0

Wow, świetna odpowiedź. Zawsze użyłem https://github.com/mfncooper/mockery do wyśmiewania całego konstruktora w pamięci podręcznej modułu wymagającego. Jest nie tylko bardziej gadatliwy, ale czasami prowadzi do testów mających naprawdę trudne do zignorowania \ błędy debugowania. Jest to świetne rozwiązanie, które jest znacznie łatwiejsze do zrozumienia. Jasmine naprawdę powinna zawierać ten przykład w swoich dokumentach. – Eric

5

Zróbmy jakiś kod refaktoryzacji jak chcemy wdrożyć konstruktora wtrysku wzór jak James Shore wspomina, że:

wtrysk Zależność oznacza rezygnację obiektowi własne zmienne instancji. Naprawdę. To jest to.

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

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

A czas dla niektórych testach

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>

Powiązane problemy