2013-02-25 17 views
17
  1. Mam aplikację internetową, która używa window.applicationCache do dostępu offline w trybie .
  2. Cały mój kod zarządzający appCache (np. Sprawdzanie/aktualizowanie/zamiana/pamięć podręczna) jest enkapsulowany do obiektu "cache-controller" .
  3. Mam testy jednostkowe, aby przetestować funkcje "pamięci podręcznej" . Do testowania tymczasowo zamieniam natywny obiekt window.applicationCache z moją własną próbną wersją (ponieważ chcę przetestować tylko kod mój, a nie implementację przeglądarki appacache), np.Wyśmiewać obiekt okna globalnego w require.js

    window.applicationCache = { /* my appCache mock */ }; 
    // unit tests run here. Code under test references window.applicationCache. 
    

Jakiś czas temu (ok. Chrome 16) podejście to działało idealnie. Następnie Chrome 17, na obu platformach Windows Mac, został usunięty z możliwości zmiany domyślnej właściwości window.applicationCache przeglądarki (co ciekawe, nadal działa dobrze w Chrome dla systemu Linux we wszystkich wersjach do Chrome 26 włącznie). W tym czasie I logged a Chromium bug; ale niestety ten raport o błędzie jest nadal wymieniony jako "niepotwierdzony".

Zresztą, właśnie przeniesiony mój wniosek z tradycyjnym „globals browser” (tj załadunku * .js poprzez znaczniki skryptów; JS. Wszystkie obiekty są globalne) do modułów AMD stylu, przy użyciu require.js jako ładowarki modułu.

Jedną z zalet AMD (lub CommonJS) jest zależność wtrysku, gdzie Twój kod pobiera lokalne odniesienie do wszelkich obiektów zależnych, zamiast polegać na globalnym odniesienia, np.

require(['foo'], function(Foo) { 
    var bar = new Foo(); 
}); 

... co sprawia, że ​​można je łatwo usunąć obiekt wyśmianie, ponieważ można skonfigurować moduł ładujący przekazać atrapa obiektu dla „foo” w trybie testowym.

Miałem nadzieję, że przenosząc się do uzależnienia od wstrzyknięcia, mogę obejść moim applicationCache emisji (jako „okno” odniesienia przeszedł do moich modułów może być albo globalny okno przedmiot lub atrapa obiektu).

Jednak nie jestem pewien, jak mieć require.js wstrzyknąć "okno" jako zależność w moje moduły?

Czy jest możliwe (być może przy użyciu shim config?) Zdefiniowanie modułu "okna"; które można następnie przekazać do dowolnego kodu działającego na globalnym obiekcie "window"? Tak, że mogę zrobić coś takiego:

require(['???'], function(window) { 
    // 'window' here is the real window object, or for testing it's a mock window object 
    window.applicationCache.update(); 
}); 

... gdzie '???' jest nazwą modułu, która odnosi się do obiektu okna.

Czy potrzebowałbym zdefiniować własny moduł, który eksportuje "okno", które można inaczej odwzorować na testowanie jednostkowe, np.

// window.js 
define(function() { 
    return window; // real global window object 
}); 

// window-mock.js 
define(function() { 
    return { 
    applicationCache: { /* mock version of appCache */ } 
    } 
}); 

// for unit testing, remap 'window' to the mock version 
require.config({ 
    map: { 
    "cache-controller": { 
     "window": "window-mock" 
    } 
    } 
}); 

// cache-controller.js 
require(['window'], function(window) { 
    window.applicationCache.update(); 
}); 

Odpowiedz

6

Odpowiedziałem na własne pytanie. Zdecydowałem się utworzyć moduły window.js i window-mock.js, jak opisano powyżej, co pozwoliło mi przekazać wersję próbną podczas uruchamiania testów jednostkowych i używać "prawdziwego" obiektu okna podczas normalnego działania.