6

如何对以下场景的不同视图进行单元测试

.state('app.sr.product.upload', {
            name: 'upload',
            url: '/upload',
            data: {
                tags: [],
                userCommunities: []
            },
            views: {
                "productView@app.sr.product": {
                    templateUrl: 'views/upload/upload.html',
                    controller: 'UploadCtrl',
                    controllerAs: 'ul'
                },
                "tags@app.sr.product.upload": {
                    templateUrl: 'views/tags/tags.html',
                    controller: 'TagsCtrl',
                    controllerAs: 'vm'
                },
                "UserCommunityPanel@app.sr.product.upload": {
                    templateUrl: 'views/user-community/user-community.html',
                    controller: 'UserCommunityCtrl',
                    controllerAs: 'ul'
                },
            }
        })
  • 如果我的观点是,tags@app.sr.product.upload那么我如何测试我的控制器是 TagsCtrl,我的 controllerAs 值是 vm 等?

  • app.sr.product.upload如果我的状态是这样 ,我该如何进行单元测试data.tags=[], data.userCommunities=[]

我搜索了很多文档和教程,但没有得到它。

任何帮助都是可观的。谢谢

4

3 回答 3

5

试穿这个尺寸。我假设您将使用 jasmine 进行测试,但任何测试框架的概念都是相同的。

运行测试时,首先订阅'$stateChangeSuccess'事件,然后导航到该状态。事件触发后,检查 toState 值以查看它们是否符合您的预期。

您可以运行该代码段以查看正在运行的测试。

//write a unit test
describe('state changes', function() {
  beforeEach(module('app'));
  var $rootScope, $state;
  beforeEach(inject(function(_$rootScope_, _$state_) {
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $rootScope = _$rootScope_;
    $state = _$state_;
  }));


  it('loads page 1', function(done) {
    //wait for the state to change, then make sure we changed to the correct state
    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
      expect(toState.controller).toEqual('Controller1');
      done();
    });
    //navigate to the state
    $state.go('state1');
    //start a digest cycle so ui-router will navigate
    $rootScope.$apply();
  });

  it('loads page 2', function(done) {
    //wait for the state to change, then make sure we changed to the correct state
    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
      expect(toState.controller).toEqual('Controller2');
      done();
    });
    //navigate to the state
    $state.go('state2');
    //start a digest cycle so ui-router will navigate
    $rootScope.$apply();
  });

  it('loads page 3', function(done) {
    //wait for the state to change, then make sure we changed to the correct state
    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
      expect(toState.controller).toEqual('Controller3');
      done();
    });
    //navigate to the state
    $state.go('state3');
    //start a digest cycle so ui-router will navigate
    $rootScope.$apply();
  });
});

//set up some dummy controllers and some dummy states
angular.module('app', ['ui.router']).controller('Controller1', function() {
  this.message = 'Page 1';
}).controller('Controller2', function() {
  this.message = 'Page 2';
}).controller('Controller3', function() {
  this.message = 'Page 3';
}).config(function($stateProvider, $urlRouterProvider) {
  $urlRouterProvider.otherwise("/state1");

  $stateProvider.state('state1', {
    url: "/state1",
    controller: 'Controller1',
    controllerAs: 'vm',
    template: '<h1>{{vm.message}}</h1>'
  }).state('state2', {
    url: "/state2",
    controller: 'Controller2',
    controllerAs: 'vm',
    template: '<h2>{{vm.message}}</h2>'
  }).state('state3', {
    url: "/state3",
    controller: 'Controller3',
    controllerAs: 'vm',
    template: '<h3>{{vm.message}}</h3>'
  });
});
h1 {
  color: red;
}
h2 {
  color: blue;
}
h3 {
  color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>

<script src="
https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<link rel="stylesheet" type="text/css" href="http://jasmine.github.io/2.0/lib/jasmine.css">
<script src="http://jasmine.github.io/2.0/lib/jasmine.js"></script>
<script src="http://jasmine.github.io/2.0/lib/jasmine-html.js"></script>
<script src="http://jasmine.github.io/2.0/lib/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-mocks.js"></script>
<div ng-app="app">
  <a ui-sref="state1">State 1</a>
  <a ui-sref="state2">State 2</a>
  <a ui-sref="state3">State 3</a>
  <div ui-view></div>
</div>

于 2016-03-10T22:05:41.790 回答
1

如果我没记错的话,我认为我们错过了最初问题的重点,即

如果我的视图是 tags@app.sr.product.upload 那么我如何测试我的控制器是 TagsCtrl,我的 controllerAs 值是 vm 等?

如果我的状态是 app.sr.product.upload 然后 data.tags=[], data.userCommunities=[] 等,我该如何进行单元测试?

以下是测试这些的方法:

var $rootScope, $state, $injector, state;

beforeEach(inject(function(_$rootScope_, _$state_){
    $rootScope = _$rootScope_;
    $state = _$state_;
    state = $state.get('app.sr.product.upload');
}));

it('should have the correct data parameters', function () {

    expect(state.data.tags).toEqual('');
    expect(state.data.userCommunities).toEqual('');

});

it('should render the dashboard views with the right Controllers', function () {

    var product = state.views['productView@app.sr.product'];
    var tags= state.views['tags@app.sr.product.upload'];
    var userCommunity = state.views['UserCommunityPanel@app.sr.product.upload'];

    expect(product.templateUrl).toEqual('views/upload/upload.html');
    expect(product.controller).toEqual('UploadCtrl');
    expect(product.controllerAs).toEqual('ul');

    // etc...

});

此外,在较新的角度版本中,您可以像这样声明您的控制器:

controller: 'UploadCtrl as vm'
于 2016-07-28T13:43:58.633 回答
0

这不是我通常会进行单元测试的东西。UI-Router 本身已被测试很好地覆盖

使用Protractor进行 e2e(端到端)测试会做得更好。您模拟点击链接,您希望 url 是这样的,使用预期列表中的元素数量是这样的等等。

但如果你真的需要它:

  • 定位每个视图的根元素(通过添加特定的类和使用选择器)
  • 您应该能够通过 angular.element 包装方法访问范围和控制器
于 2016-03-08T21:09:11.610 回答