2015-01-27 5 views
5

Sto usando il codice qui sotto per reimpostare $broadcast dopo ogni caso di test, ma sembra che $rootScope.$broadcast.reset(); non funzioni correttamente, dal momento che il test qui sotto dovrebbe restituire 1, ma restituisce 6.Ripristina broadcast() dopo ogni caso di test durante l'utilizzo di eCallThrough()

sembra che la ragione di questo è andCallThrough(), dal momento che prima ho usato senza andCallThrough() funzione, ma dopo un po 'refactoring mi ha dato un errore che TypeError: Cannot read property 'defaultPrevented' of undefined, così ho dovuto usare per evitare tale errore.

La domanda è: come posso ripristinare lo broadcast durante l'utilizzo di andCallThrough oppure esiste un altro approccio più preciso?

beforeEach(function() { 
    spyOn($http, 'post'); 
    spyOn($rootScope, '$broadcast').andCallThrough(); 
}); 

afterEach(function() { 
    $http.post.reset(); 
    $rootScope.$broadcast.reset(); 
}); 

it('should make a POST request to API endpoint', function() { 
    $http.post.andCallThrough(); 
    var response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' }; 
    $httpBackend.expectPOST(apiUrl + 'login').respond(response); 
    service.login(); 
    $httpBackend.flush(); 
    $timeout.flush(); 
    expect($rootScope.$broadcast.callCount).toBe(1); 
    expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response); 
}); 
+1

Se la chiamata a "aspettarsi" di testare "callCount" viene spostata sulla prima riga del test, cosa significa "callCount" uguale poi? Mi chiedo se qualcos'altro nel test sta chiamando '$ broadcast'. –

risposta

4

Dopo lunga indagine di come funzionano le cose in questa situazione, infine, i test sono passati e la soluzione è l'attuale:

Il problema non era di circa reseting broadcast() o reset metodo non viene chiamato dopo dopo ogni prova caso durante l'utilizzo di andCallThrough(). Il problema è che il $rootScope.$broadcast.andCallThrough(); viene attivato da altri eventi e la funzione .callCount() restituita 6, che in pratica significa che la spia $broadcast è stata chiamata 6 volte.Nel mio caso sono interessato solo all'evento AUTH_EVENTS.loginSuccess e mi assicuro che sia stato trasmesso una sola volta.

expect($rootScope.$broadcast.callCount).toBe(1); 
expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response); 

Così scavare il metodo di $rootScope.$broadcast.calls dato il mio matrice di tutte le chiamate da cui i due aspetta sopra dovrebbero essere recuperati. Di conseguenza, la soluzione è:

it('should make a POST request to API endpoint', function() { 
    $http.post.andCallThrough(); 
    var response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' }; 
    $httpBackend.expectPOST(apiUrl + 'login').respond(response); 
    service.login(); 
    $httpBackend.flush(); 
    $timeout.flush(); 

    var loginSuccessTriggerCount = _($rootScope.$broadcast.calls) 
    .chain() 
    .map(function getFirstArgument(call) { 
     return call.args[0]; 
    }) 
    .filter(function onlyLoginSuccess(eventName) { 
     return eventName === AUTH_EVENTS.loginSuccess; 
    }) 
    .value().length; 

    expect(loginSuccessTriggerCount).toBe(1); 
}); 
2

Un approccio diverso. È uno pseudo-codice simile a un coffeescript. Chiedi nei commenti se alcune espressioni non sono chiare. Dovrebbe dire che non è una risposta diretta alla tua domanda. Solo un metodo per fare cose simili in un altro modo.

Test con lo stato più puro

Lasciate che introducono una variabile che gestirà una spia per la trasmissione. Io uso spie pure perché lo spyOn può funzionare male in alcuni casi ingombranti quando ci occupiamo di sovrascrivere o mixare il metodo.

rootScope$broadcastSpy = jasmine.createSpy() 

Abbiamo bisogno di scambiare realizzazione origine con un stub che gestirà le spie ei loro stati. La solita definizione di stub dice che è un'entità che non ha una sua logica. Quindi, lo facciamo in modo puro e non mettiamo alcuna logica qui. Solo un marcatore (che è rappresentato da una spia).

beforeEach module ($provide) -> 
    $provide.value '$rootScope', 
    $broadcast: rootScope$broadcastSpy 

    return 

Certo, abbiamo bisogno di parlare di gelsomino quando abbiamo bisogno di resettare una spia.

beforeEach -> 
    rootScope$broadcastSpy.reset() 

Definiamo portata test dove ci prepareremo tutti i servizi necessari e metterli in un modo dichiarativo al contesto (vale a dire this).

instance = (fnAsserts) -> 
    inject (loginService, $httpBackend, $timeout, apiUrl, AUTH_EVENTS) -> 
    fnAsserts.call 
     service: loginService 
     apiUrl: apiUrl 
     AUTH_EVENTS: AUTH_EVENTS 
     '$httpBackend': $httpBackend 
     '$timeout': $timeout 

Scriviamo il test in modalità blackbox. Configuriamo semplicemente lo stato iniziale, quindi iniziamo un'azione e alla fine controlliamo il nostro indicatore per le modifiche.

it 'should make a POST request to API endpoint', instance -> 
    # Given 
    response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' } 
    @$httpBackend.expectPOST(@apiUrl + 'login').respond(response) 

    # When 
    @service.login() 

    # Then 
    @$httpBackend.flush() 
    @$timeout.flush() 
    expect(rootScope$broadcastSpy.callCount).toBe(1) 
    expect(rootScope$broadcastSpy).toHaveBeenCalledWith(@AUTH_EVENTS.loginSuccess, response) 

Come potete vedere possiamo defitions esempio a catena, aggiungere altre informazioni a loro e scrivere ogni test in modo più puro perché vediamo lo stato, il campo di applicazione, deride e altre cose necessarie in unico luogo. Usiamo una chiusura solo per il marcatore e garantisce che gli effetti collaterali siano minimizzati.

+0

Grazie a @Gulin per la risposta, poiché non conosco CoffeeScript questa soluzione non è chiara. In particolare, la funzione 'beforeEach module ($ provide) -> \ n $ provide.value '$ rootScope', \ n $ broadcast: rootScope $ broadcastSpy \ n return' Cosa restituisce' return'? – Max

+0

Nel caffè ogni riga è un ritorno. Ma qui ho inserito il reso esplicitamente per non restituire nulla. L'implementazione 'module' usa il valore restituito ed evito questo comportamento restituendo 'undefined' tramite return vuoto. –

0

Ho finito qui per la prima parte della domanda

reset trasmissione()

e questo funziona per me:

$rootScope.$broadcast.calls.reset()