Подтвердить что ты не робот

UI-маршрутизатор взаимодействует с $httpbackend unit test, angular js

Это контроллер с функцией отправки:

$scope.submit = function(){   

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

Это мой тест

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);
  });

Ошибка, которую я получаю:

Error: Unexpected request: GET views/appBar.html

views/appBar.html - это мой шаблон url:

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

Итак, как-то ui-router делает мой пункт $httpBackend для этого вместо моей функции отправки. У меня такая же проблема во всех моих тестах, используя $httpBackend.

Есть ли какое-либо решение для этого?

4b9b3361

Ответ 1

Возьмите этот смысл 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!");
        }
    }
});

Добавьте его в файл с именем stateMock в папке test/mock, включите этот файл в конфигурацию вашей кармы, если он еще не был выбран.

Настройка перед вашим тестом должна выглядеть примерно так:

beforeEach(module('stateMock'));

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

Затем в вашем тесте вы должны добавить

state.expectTransitionTo('project');

Ответ 2

Этот вопрос Github о Unit Testing UI Router более подробно объясняет, что происходит.

Проблема заключается в том, что $httpBackend.flush() запускает широковещательную передачу, которая затем запускает в противном случае случай stateProvider.

Простым решением может быть следующая настройка, о которой упоминается в статье @darinclark в упомянутой выше статье Github. Это действительно, если вам не нужно проверять состояние переходов. В противном случае посмотрите @rosswil answer, который вдохновлен @Ответ Vratislav на Github.

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

EDITED

Спасибо Крису Т сообщить об этом в комментариях, кажется, после v0.2.14? лучший способ сделать это - использовать

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

Ответ 3

Если вы не хотите добавлять gist файлы, как указано в правильном решении, вы можете добавить условие "когда" к вашему $httpBackend, чтобы игнорировать петиции GET видов вроде этого:

$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();

Ответ 4

У меня такая же ошибка, о которой вы прокомментировали, после службы вызова они спрашивают меня о URL-адресе другого маршрута ui.

Чтобы решить проблему вызова, иначе ui-route при тестировании не введет $state в beforeach. В моем тестировании $state не имеет смысла использовать его.

Ответ 5

Переместите свои службы в собственный модуль, не зависящий от ui.router. ваше основное приложение зависит от этого модуля. Когда вы тестируете не тестируете основное приложение, проверьте модуль, в котором есть ваши службы. Stateprovider не будет пытаться изменить состояние/маршрут, потому что этот модуль ничего не знает о ui.router. Это сработало для меня.