Interfaces de interface do usuário com teste de unidade de httpbackend, js angular

Este é um controlador com uma function de envio:

$scope.submit = function(){ $http.post('/api/project', $scope.project) .success(function(data, status){ $modalInstance.dismiss(true); }) .error(function(data){ console.log(data); }) } } 

Este é o meu teste

 it('should make a post to /api/project on submit and close the modal on success', function() { scope.submit(); $httpBackend.expectPOST('/api/project').respond(200, 'test'); $httpBackend.flush(); expect(modalInstance.dismiss).toHaveBeenCalledWith(true); }); 

O erro que recebo é:

 Error: Unexpected request: GET views/appBar.html 

views / appBar.html é meu templateUrl:

  .state('project', { url: '/', templateUrl:'views/appBar.html', controller: 'ProjectsCtrl' }) 

Então, de alguma forma, o ui-router está fazendo o meu $ httpBackend apontar para isso em vez da minha function de envio. Eu tenho o mesmo problema em todos os meus testes usando $ httpBackend.

Existe alguma solução para isso?

Tome este gist https://gist.github.com/wilsonwc/8358542

 angular.module('stateMock',[]); angular.module('stateMock').service("$state", function($q){ this.expectedTransitions = []; this.transitionTo = function(stateName){ if(this.expectedTransitions.length > 0){ var expectedState = this.expectedTransitions.shift(); if(expectedState !== stateName){ throw Error("Expected transition to state: " + expectedState + " but transitioned to " + stateName ); } }else{ throw Error("No more transitions were expected! Tried to transition to "+ stateName ); } console.log("Mock transition to: " + stateName); var deferred = $q.defer(); var promise = deferred.promise; deferred.resolve(); return promise; } this.go = this.transitionTo; this.expectTransitionTo = function(stateName){ this.expectedTransitions.push(stateName); } this.ensureAllTransitionsHappened = function(){ if(this.expectedTransitions.length > 0){ throw Error("Not all transitions happened!"); } } }); 

Adicione-o a um arquivo chamado stateMock na sua pasta de teste / simulação, inclua esse arquivo na sua configuração karma se ele não estiver selecionado.

A configuração antes do seu teste deve ser algo como isto:

 beforeEach(module('stateMock')); // Initialize the controller and a mock scope beforeEach(inject(function ($state //other vars as needed) { state = $state; //initialize other stuff } 

Então no seu teste você deve adicionar

 state.expectTransitionTo('project'); 

Esta edição do Github sobre roteador de teste de unidade explica mais detalhadamente o que está acontecendo.

O problema é que $httpBackend.flush() triggers uma transmissão que triggers o caso contrário do stateProvider .

Uma solução simples pode ser fazer a seguinte configuração, conforme mencionado por @darinclark no tópico Github mencionado acima. Isso é válido se você não precisar testar transições de estado. Caso contrário, dê uma olhada na resposta do @ rosswil que é inspirada pela resposta do @Vratislav no Github .

 beforeEach(module(function ($urlRouterProvider) { $urlRouterProvider.otherwise(function(){return false;}); })); 

EDITADO

Graças a Chris T para relatar isso nos comentários, parece após v0.2.14? a melhor maneira de fazer isso é usar

 beforeEach(module(function($urlRouterProvider) { $urlRouterProvider.deferIntercept(); })); 

Se você não quiser adicionar arquivos GIST como diz na solução correta, você pode adicionar uma condição “when” ao seu $ httpBackend para ignorar petições de visualizações como esta:

 $httpBackend.when("GET", function (url) { // This condition works for my needs, but maybe you need to improve it return url.indexOf(".tpl.html") !== -1; }).passThrough(); 

Eu tenho o mesmo erro que você comentou, depois de um serviço de chamadas, eles me perguntam sobre a URL do caminho de outra forma.

Para resolver o problema de chamar a rota ui em contrário no teste não é injetado $ state em beforeach statment . No meu teste $ state não tem sentido em usá-lo.

Mova seus serviços para seus próprios módulos que não dependam do ui.router. ter seu aplicativo principal depende deste módulo. Quando você testar não testar o aplicativo principal, teste o módulo que tem seus serviços nele. O provedor de estado não tentará alterar o estado / rota porque este módulo não sabe nada sobre o ui.router. Isso funcionou para mim.