2015-06-21 12 views
6

Co chcę zrobić: Piszemy kilka testów dla istniejącej bazy kodu JavaScript, która używa mocno jQuery. Do testów nie chcemy mieć rzeczywistych elementów HTML (urządzeń HTML). Wolimy, jeśli mamy obiekt symulujący jQuery, który nie robi nic związanego z HTML.Jak wyśmiać jQuery z Jasmine

Mój punkt wyjścia: Najbardziej obiecującym podejściem znalazłem tutaj:

http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/

Stwarza to metody pomocnika, który tworzy makiety przechodząc przez funkcje obiektu i stworzenie szpiega dla każdego funkcja:

window.mock = function (constr, name) { 
    var keys = []; 
    for (var key in constr.prototype) 
    keys.push(key); 
    return keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {}; 
}; 

Następnie, jeśli rozumiem go poprawnie, używa on, że podobnie jak to (dostosowany przykład z jego blogu):

var el = mock($); 
el('.some-not-existing-class').css('background', 'red'); 
expect(el.css).toHaveBeenCalledWith('background', 'red'); 

Jednak to nie działa, ponieważ el jest object a nie function.

Moje podejście do rozwiązania tego problemu: I refactored jego mock funkcji celu uwzględnienia przypadku, constr jest function:

mock (constr, name) { 
    var keys = []; 
    for (var key in constr.prototype) 
    keys.push(key); 
    var result = keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {}; 

    // make sure that if constr is a function (like in the case of jQuery), the mock is too 
    if (typeof constr === 'function') { 
    var result2 = result; 
    result = jasmine.createSpy(name || 'mock-fn'); 
    for (var key in result2) 
     result[key] = result2[key]; 
    } 
    return result; 
} 

jednak druga linia w teście wyrzuca błąd Cannot read property css of undefined:

var el = mock($); 
el('.some-not-existing-class').css('background', 'red'); 
expect(el.css).toHaveBeenCalledWith('background', 'red'); 

Inne pomysły: próbowałem też połączyć obiekt szpiegowski i nto jQuery, ale to też nie pomogło.

Wszelkie pomysły? Mam nadzieję, że nie jesteśmy jedynymi, którzy robią to bez urządzeń HTML.

Odpowiedz

0

Znaleziono. Kiedy moja wersja funkcji mock jest skonfigurowana, aby powrócić obiektu jQuery, gdy funkcja jQuery jest wywoływany, test działa:

mock (constr, name) { 
    var keys = []; 
    for (var key in constr.prototype) 
    keys.push(key); 
    var result = keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {}; 

    // make sure that if constr is a function (like in the case of jQuery), the mock is too 
    if (typeof constr === 'function') { 
    var result2 = result; 
    result = jasmine.createSpy(name || 'mock-fn'); 
    result.and.returnValue(result); 
    for (var key in result2) 
     result[key] = result2[key]; 
    } 
    return result; 
} 
0

Możesz użyć sinon.js stubs, zamiast obracać własne metody pomocnicze.

stub = sinon.stub(jQuery.fn, 'css'); 

// invoke code which calls the stubbed function 

expect(stub.calledWith({ 'background': 'red' })).toBe(true); 
stub.restore(); 
+0

próbowałem tego z linią '$ („abc”) css („background”. , "czerwony"); "jako kod testowy. Jednak assert nie powiedzie się, "sub.calledWith" zwraca false. – cheeesus