2015-02-25 13 views
8

Sto usando la sintassi "controller come" per creare il mio controller. Ho una funzione di inizializzazione privata che chiama una funzione per caricare i dati predefiniti.Come spio un metodo di controllo usando Jasmine?

var app = angular.module('plunker', []); 

app.controller('MainCtrl', function($scope) { 
    var mc = this; 
    mc.dataLoaded = false; 

    function init() { 
    mc.loadData(); 
    } 

    mc.loadData = function(){ 
    mc.dataLoaded = true; 
    } 

    init(); 
}); 

Nella mia prova Sto creando una spia per verificare se la funzione loadData è stato chiamato. Anche se posso verificare che la funzione sia stata chiamata testando il flag mc.dataLoaded, la mia spia non sembra registrare la funzione chiamata. Come posso convincere la spia a registrare correttamente la chiamata di funzione?

describe('Testing a Hello World controller', function() { 
    var $scope = null; 
    var ctrl = null; 

    //you need to indicate your module in a test 
    beforeEach(module('plunker')); 

    beforeEach(inject(function($rootScope, $controller) { 
    $scope = $rootScope.$new(); 

    ctrl = $controller('MainCtrl as mc', { 
     $scope: $scope 
    }); 

    spyOn($scope.mc, 'loadData').and.callThrough(); 
    })); 

    it('should call load data', function() { 
    expect($scope.mc.loadData).toHaveBeenCalled(); 
    //expect($scope.mc.dataLoaded).toEqual(false); 
    }); 
}); 

Plunker link

risposta

9

Questa sequenza di linee:

ctrl = $controller('MainCtrl as mc', { 
    $scope: $scope 
}); 

spyOn($scope.mc, 'loadData').and.callThrough(); 

significa che la spia Jasmine si crea dopo il controller è già stata creata un'istanza di $ controller. Prima che la spia venga creata, la funzione init è già stata eseguita.

Non è possibile cambiare le linee intorno, perché MainCtrl deve esistere prima di poter spiare un metodo su di esso.

Se la funzione init chiama un altro servizio, quindi spiare il metodo di quel servizio e asserire che il servizio è chiamato correttamente. Se MainCtrl sta semplicemente facendo qualcosa internamente, prova il risultato di ciò, ad esempio, affermando che i dati/proprietà del controllore vengono aggiornati. Potrebbe non valere la pena di testare se è abbastanza banale.

Inoltre, dal momento che si sta utilizzando il controller come sintassi, è possibile fare riferimento al controller tramite il valore di ritorno di chiamare $ regolatore, piuttosto che accedere direttamente la portata:

ctrl = $controller('MainCtrl as mc', { 
    $scope: $scope 
}); 

ctrl.loadData === $scope.mc.loadData; // true 
+2

Domanda forse fuori ambito ... Potrebbe essere possibile spiare una funzione che non è in $ scope? Voglio dire, spiare 'init' in quel codice. –

+1

"Se MainCtrl sta facendo qualcosa internamente, prova il risultato di ciò, ad esempio, affermando che i dati/proprietà del controller sono aggiornati. Potrebbe non valere la pena di testare se è abbastanza banale." QUESTO DEVE ESSERE DATO! –

+0

E il codice di inizializzazione del controller interno non si basa su un altro servizio, è abbastanza complesso da richiedere il test e non ha effetti collaterali sulle proprietà dell'ambito? La tua unica opzione è spostare il codice di inizializzazione in un altro servizio? Sembra un peccato rendere il tuo codice più complicato solo per abilitare i test unitari. – d512

1

ho trovato una soluzione che ha permesso per evitare di cambiare il mio controller Ho incluso un servizio di finto $state nel metodo beforeEach della suite di test, e ha dato un metodo reload finto:

beforeEach(inject(function ($controller, $rootScope) { 
    stateMock = { 
     reload: function() { 
      myCtrl = $controller('MyCtrl'); 
     } 
    }; 
    ... 

Poi nei test di gelsomino, posso semplicemente chiamare stateMock.reload() di ri-inizializzare il mio controller, preservando le mie spie mi dichiarato in un altro blocco beforeEach.

+0

Funziona davvero? Stai creando un nuovo oggetto controller in modo che le spie che hai dichiarato in precedenza non vengano eliminate con il vecchio oggetto controller? – d512

+0

Ha funzionato per la mia squadra. Verificato cambiando temporaneamente i test di Jasmine per fallire con valori inaspettati. Ha generato errori per te? – dpfrakes

Problemi correlati