Контроллер модульного тестирования, который использует $state.transitionTo

внутри контроллера у меня есть функция, которая использует $state.transitionTo для «перенаправления» в другое состояние.

теперь я застрял в тестировании этой функции, я всегда получаю ошибку Error: No such state 'state-two'. как я могу проверить это? Мне совершенно ясно, что контроллер ничего не знает о других состояниях, но как я могу издеваться над этим состоянием?

некоторый код:


angular.module( 'mymodule.state-one', [
  'ui.state'
])

.config(function config($stateProvider) {
  $stateProvider.state('state-one', {
    url: '/state-one',
    views: {
      'main': {
        controller: 'MyCtrl',
        templateUrl: 'mytemplate.tpl.html'
      }
    }
  });
})

.controller('MyCtrl',
  function ($scope, $state) {
    $scope.testVar = false;
    $scope.myFunc = function () {
      $scope.testVar = true;
      $state.transitionTo('state-two');
    };

  }
);

describe('- mymodule.state-one', function () {

  var MyCtrl, scope

  beforeEach(module('mymodule.state-one'));

  beforeEach(inject(function ($rootScope, $controller) {

    scope = $rootScope.$new();

    MyCtrl = $controller('MyCtrl', {
      $scope: scope
    });

  }));

  describe('- myFunc function', function () {
    it('- should be a function', function () {
      expect(typeof scope.myFunc).toBe('function');
    });

    it('- should test scope.testVar to true', function () {
      scope.myFunc();
      expect(scope.testVar).toBe(true);
      expect(scope.testVar).not.toBe(false);
    });
  });
});

person Community    schedule 10.07.2013    source источник


Ответы (3)


Отказ от ответственности: я не делал этого сам, поэтому я совершенно не знаю, сработает ли это, и это то, что вам нужно.

Мне в голову приходят два решения.

1.) В ваших тестах предварительно настройте $stateProvider для возврата фиктивного состояния для state-two Это также то, что делает сам проект ui-router для проверки переходов состояний.

См.: https://github.com/angular-ui/ui-router/blob/04d02d087b31091868c7fd64a33e3dfc1422d485/test/stateSpec.js#L29-L42

2.) поймать и разобрать исключение и интерпретировать его как выполненный тест, если пытается добраться до state-two

Второй подход кажется очень хакерским, поэтому я бы проголосовал за первый.

Тем не менее, есть вероятность, что я совершенно неправильно вас понял и, вероятно, должен немного отдохнуть.

Код решения:

beforeEach(module(function ($stateProvider) { 
  $stateProvider.state('state-two', { url: '/' }); 
}));
person Christoph    schedule 10.07.2013
comment
Спасибо! что я добавил в свои тесты: beforeEach(module(function ($stateProvider) { $stateProvider.state('state-two', { url: '/' }); })); - person ; 11.07.2013
comment
Ваша ссылка больше не указывает на то, на что, по вашему мнению, она должна указывать. Может стоит указать на конкретную ревизию? - person George Stocker; 05.05.2015

Недавно я задал этот вопрос как проблему с github, и на него ответили очень полезно. https://github.com/angular-ui/ui-router/issues/537

Вы должны сделать $rootScope.$apply(), а затем иметь возможность протестировать. Обратите внимание, что по умолчанию, если вы используете templateUrl, вы получите «неожиданный запрос GET» для представления, но вы можете решить эту проблему, включив свои шаблоны в свой тест.

'use strict';

describe('Controller: CourseCtrl', function () {

  // load the controller's module
  beforeEach(module('myApp'));

  // load controller widgets/views/partials
  var views = [
    'views/course.html',
    'views/main.html'
  ];

  views.forEach(function(view) {
    beforeEach(module(view));
  });

  var CourseCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    CourseCtrl = $controller('CourseCtrl', {
      $scope: scope
    });
  }));

  it('should should transition to main.course', inject(function ($state, $rootScope) {
    $state.transitionTo('main.course');
    $rootScope.$apply();
    expect($state.current.name).toBe('main.course');
  }));
});
person zdwolfe    schedule 30.10.2013

Также, если вы хотите ожидать, что переход был сделан так

expect(state.current.name).toEqual('state-two')

тогда вам нужно scope.$apply перед expect() чтобы он работал

person Dashu    schedule 20.09.2013