2012-07-12 18 views
21

sto cercando di testare un controller che dipende da un servizio io stesso ho costruito. Mi piacerebbe prendere in giro questo servizio dal momento che il servizio parla al DOM.Iniettando un servizio finto per un test di controllo angularjs

Ecco il mio test in corso:

describe('Player Controllers', function() { 

    beforeEach(function() { 
     this.addMatchers({ 
      toEqualData: function (expected) { 
       return angular.equals(this.actual, expected); 
      } 
     }); 
    }); 

    describe('TestPSPlayerModule', function() { 
     var $httpBackend, scope, ctrl; 

     beforeEach(module('PSPlayerModule')); 

     beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 
      $httpBackend = _$httpBackend_; 

      scope = $rootScope.$new(); 
      ctrl = $controller(PlayerController, { $scope: scope }); 
     })); 

     it('should request a clip url from the server when clipClicked is called', function() { 
      expect(1).toBe(1); 
     }); 
    }); 

}); 

mio regolatore di simile a questa:

w.PlayerController = function ($scope, $http, $window, speedSlider, $location) { 
    ... 
} 

quindi è lo speedSlider che voglio prendere in giro.

ho avuto l'idea di utilizzare un modulo che ho creato nel mio codice di prova che potrebbe fornire un'implementazione falso del cursore della velocità, così ho aggiunto quanto segue alla parte superiore del file test.js:

module('TestPSPlayerModule', []).factory('speedSlider', function() { 
    return = { 
     ... 
    }; 
}); 

e quindi elencare quel modulo nel beforeeach() chiamata al posto di quella concreta, ma se lo faccio che ottengo il seguente errore:

Injector already created, can not register a module! 

così ho dato ci deve essere un modo migliore per me per fornire una finta implementazione di uno dei miei servizi. Qualcosa forse posso usare sinon.js per ....

+0

Hai visto questa documentazione? http://docs.angularjs.org/guide/dev_guide.services.testing_services Dove '$ window' viene preso in giro. È un esempio piuttosto semplice, ma potrebbe fornire un modello per ciò che si vuole fare. –

+0

@NoahFreitas Il collegamento che hai fornito ora è morto – Stephane

+1

@StephaneEybert, sembra che sia stato spostato e aggiornato qui: https://docs.angularjs.org/guide/services#unit-testing –

risposta

6

Assicurarsi che quando si utilizza il modulo dopo la sua definizione che non si hanno le parentesi extra. Così, invece di module('TestPSPlayer')module('TestPSPlayer',[]).

40

essere sicuri che non stai cercando di fare questo all'interno di una chiamata di funzione iniettare anche:

Questo genererà l'errore:

beforeEach(inject(function(someOtherService) { 
     module('theApp', function($provide) { 
      myMock = {foo: 'bar'}; 
      $provide.value('myService', myServiceMock); 
      someOtherService.doSomething(); 
     }); 
    })); 

Questo non:

beforeEach(function() { 
     module('theApp', function($provide) { 
      myMock = {foo: 'bar'}; 
      $provide.value('myService', myServiceMock); 
     }); 

     inject(function(someOtherService) { 
      someOtherService.doSomething(); 
     }); 
    }); 
+0

più rilevante imho – davidjnelson

+7

Modulo nidificazione '() 'dentro' inject() 'non è ciò che causa l'errore. In effetti, tutte le chiamate a 'module()' devono essere _before_ 'inject()'. –

+0

@HermanKan perché? – tobi

4

In Nel mio caso questo non ha funzionato:

beforeEach(module('user')); 
beforeEach(inject(function ($http) { 
})); 

beforeEach(module('community')); 
beforeEach(inject(function ($controller, $rootScope) { 
})); 

Ho cambiato a questo per farlo funzionare:

beforeEach(module('user')); 
beforeEach(module('community')); 

beforeEach(inject(function ($http) { 
})); 
beforeEach(inject(function ($controller, $rootScope) { 
})); 
+0

questo spiega che l'iniezione dovrebbe essere chiamata DOPO tutte le inizializzazioni del modulo –

0

Se il vostro provider non usa globale init è possibile utilizzare il provider iniettato originale e deridere esso. nell'esempio qui sotto il testatoProvider è il tuo controller.

var injectedProviderMock; 

beforeEach(function() { 
    module('myModule'); 
}); 

beforeEach(inject(function (_injected_) { 
    injectedProviderMock = mock(_injected_); 
})); 


var testedProvider; 
beforeEach(inject(function (_testedProvider_) { 
    testedProvider = _testedProvider_; 
})); 

it("return value from injected provider", function() { 
    injectedProviderMock.myFunc.andReturn('testvalue'); 
    var res = testedProvider.executeMyFuncFromInjected(); 
    expect(res).toBe('testvalue'); 
}); 

//mock all provider's methods 
function mock(angularProviderToMock) { 

    for (var i = 0; i < Object.getOwnPropertyNames(angularProviderToMock).length; i++) { 
     spyOn(angularProviderToMock,Object.getOwnPropertyNames(angularProviderToMock)[i]); 
    } 
    return angularProviderToMock; 
} 
Problemi correlati