14

在控制器中,我有一个$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);
    });
  });
});
4

3 回答 3

16

免责声明:我自己没有这样做,所以我完全不知道它是否会起作用并且是你所追求的。

从我的脑海中,我想到了两个解决方案。

1.) 在您的测试中预先配置$stateProvider为返回一个模拟状态state-two这也是 ui-router 项目本身测试状态转换所做的事情。

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

2.) 捕获并解析异常并将其解释为已完成的测试,如果尝试到达state-two

第二种方法似乎很hackish,所以我会投票给第一种。

但是,很可能我完全误会了您,应该休息一下。

解决方案代码:

beforeEach(module(function ($stateProvider) { 
  $stateProvider.state('state-two', { url: '/' }); 
}));
于 2013-07-10T23:52:07.820 回答
4

我最近将这个问题作为 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');
  }));
});
于 2013-10-30T14:18:10.583 回答
2

另外,如果您希望过渡是这样进行的

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

那么你需要在它scope.$apply之前expect()工作

于 2013-09-20T19:22:50.143 回答