2014-05-07 15 views
11

Sto cercando come usare Jasmine con Karma. Sto cercando di iniettare un ambito nel mio controllore e da qualche parte ho raccolto questo codice ...

var scope = { message: 'hello' }; 

beforeEach(angular.mock.module('myApp')); 

beforeEach(angular.mock.inject(function ($rootScope, $controller) { 

    scope = $rootScope.$new(); 

    $controller('myController', { $scope: scope }); 

})); 

Il problema è che il campo di applicazione è stato spazzato via con la linea ...

scope = $rootScope.$new(); 

Quindi posso commentare, ma mi chiedo a cosa serve l'uso di questa linea? Quando dovrei chiamare lo $rootscope.$new()? Capisco che faccia dell'isolamento, ma non ne ottengo realmente le applicazioni pratiche.

AGGIORNAMENTO: Come indicato di seguito, Tim è un problema perché ho dichiarato il mio ambito. Così posso modificare il codice per essere ....

var scope; 

beforeEach(angular.mock.module('myApp')); 

beforeEach(angular.mock.inject(function ($rootScope, $controller) { 

    scope = $rootScope.$new(); 

    scope.message = 'hello'; 

    $controller('myController', { $scope: scope }); 

})); 

e che funziona più come previsto, ma sto ancora chiedendo cosa l'approccio migliore è? Che cosa è $rootscope.$new() anche per?

+0

'Il problema è il campo di applicazione è stato spazzato via con la Line' mi piacerebbe che il 'problema' reale è che si * definito * il tuo 'var scope' –

+0

Okay, questo ha senso ora che dici. Con questo in mente quale è l'approccio migliore? – Exitos

+0

Perché non usi semplicemente Yeoman e lasci che metta a punto la tua configurazione jasmine/karma? – mortsahl

risposta

3

Scopes in angolare sono annidati nei rapporti genitore-figlio, il tutto derivante da un unico genitore $rootScope

Questo è il modo angolare crea la $scope che viene iniettato nel vostro controller in modo che crea la stessa esperienza quando si è unità di testare il controller.

Ciò è particolarmente utile se si sta facendo qualcosa nel controller che richiede di chiamare $ apply piuttosto che dover prendere in giro anche questo.

11

$rootScope.$new crea una nuova istanza di $rootScope.Scope che eredita da $rootScope. In altre parole, crea un nuovo ambito figlio di $rootScope.

Il motivo per cui è possibile utilizzarlo nei test (come quello pubblicato), è perché l'altra alternativa è utilizzare lo stesso $rootScope. Ciò potrebbe creare un disastro in quanto potrebbe essere utilizzato in tutto il luogo.

Ritengo la migliore procedura per creare (e distruggere in seguito) un nuovo ambito per ogni caso di test.

Ecco il vostro esempio riscritto per quello che considero una best practice:

describe('myModule', function() { 

    var $rootScope; 

    beforeEach(module('myModule')); 

    beforeEach(function() { 
     inject(function(_$rootScope_) { 
      $rootScope = _$rootScope_; 
     }); 
    }); 

    describe('myController', function() { 

     var $scope; 

     beforeEach(function createChildScopeForTheTest() { 
      $scope = $rootScope.$new(); 
     }); 

     afterEach(function disposeOfCreatedChildScope() { 
      $scope.$destroy(); 
     }); 

     it('tests something', function() { 
      $scope.message = 'hello'; 

      $controller('myController', { $scope: $scope }); 

      expect($scope.something).toEqual('world'); 
     }); 
    }); 
}); 
+0

Mi piace questo esempio. Un problema però, ottengo un errore se provo a distruggere l'ambito in un blocco afterEach. Sembra che lo scope sia già stato ripulito e distrutto in quel punto. – SuneRadich

+1

Lo sto usando in tutti i miei test, di cui ho oltre 10000. Non ho mai avuto questo problema.Potrebbe essere dovuto a qualcos'altro che stai facendo nel tuo test. Pubblica un po 'di codice se vuoi aiuto a risolverlo :-) – eitanfar

Problemi correlati