12

Supponiamo che io sono un servizio che dipende da un valore in $ rootScope, come con il seguente servizio di (banale):

angular.module('myServices', []) 
.factory('rootValGetterService', function($rootScope) { 
    return { 
     getVal: function() { 
      return $rootScope.specialValue; 
     } 
    }; 
}); 

Se voglio unit test questo mettendo un valore in $ rootScope, qual è la miglior modo per farlo?

risposta

6

Utilizzando fornire(), si può iniettare un nuovo $ rootScope:

describe('in rootValGetter', inject(function ($rootScope) { 
    var scope; 
    var testRootValGetter; 

    beforeEach(function() { 

     scope = $rootScope.$new(); 

     module(function ($provide) { 
      $provide.value('$rootScope', scope); 
     }); 

     inject(function ($injector) { 
      testRootValGetterService = $injector.get('rootValGetterService'); 
     }); 
    }); 

    it('getVal returns the value from $rootScope', function() { 
     var value = 12345; 

     scope.specialValue = value; 

     expect(testRootValGetterService.getVal()).toBe(value); 
    } 
} 
+12

Questo schema non funziona per me. Angolare continua a lanciare questo errore: "Errore: iniettore già creato, impossibile registrare un modulo!" – Espilon

+0

Perché è necessario usare 'scope = $ rootScope. $ New();', invece di usare '$ rootScope' direttamente? –

+1

Perché voglio eseguire test di unità isolati l'uno dall'altro. –

3

Includere angular-mocks.js, quindi utilizzare angular.mock.inject:

+1

Il collegamento ai documenti non è aggiornato, il collegamento corrente è: https://docs.angularjs.org/api/ngMock/function/angular.mock.inject –

+0

@ GregoryAvery-Weir, grazie! Corretto – L42y

21
... 
var $rootScope; 
beforeEach(inject(function(_$rootScope_) { 
    $rootScope = _$rootScope_; 
})); 
... 
+0

Questo non ti dà lo stesso scopo per ogni test? Come passi un nuovo ambito al servizio? – Tamlyn

+0

Ciao Tamlyn, in che modo la tua root non è più fresca? credo di averlo sempre usato per trasmettere eventi –

+1

I caratteri di sottolineatura sono necessari perché altrimenti esiste un conflitto di denominazione tra '$ rootScope' nella chiusura e l'argomento' $ rootScope'. –

0

Basta cercare di dare una risposta più dettagliata tra cui il test caso:

...

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

...

it('getVal returns the value from $rootScope', function() { 
     var value = 12345; 
     $rootScope.specialValue = value; 
     expect(testRootValGetterService.getVal()).toBe(value); 
    } 
0

Ecco quello che ho fatto:

it('some kind of wacky test', function($rootScope, Translate){ 
    $rootScope.lang = 'en'; 
    expect(Translate('overview').toBe('Overview'); 
} 
0

Spero che questo aiuti gli altri come questa era la soluzione a un problema simile.

var rootValGetterService; 

beforeEach(inject(function($rootScope,$injector) { 
    $rootScope.specialValue = "test"; 
    rootValGetterService= $injector.get('rootValGetterService'); 
})); 

it("Should have a service", function() { 
    expect(rootValGetterService).toBeDefined(); 
}); 
0

Invece di creare un nuovo ambito come si farebbe se si stesse iniettando $scope si può deridere le proprietà è necessario direttamente in $rootScope.

Quindi $rootScope verrà iniettato con quelle proprietà disponibili nel codice che si sta testando.

Almeno questo è il modo in cui ho risolto lo stesso problema.

Il seguente codice dovrebbe funzionare nel tuo esempio.

beforeEach(inject(function($rootScope) { 
    $rootScope.specialValue = 'whatever'; 
})); 
Problemi correlati