单元测试视图 - 最佳实践
单元测试视图 - 最佳实践
有人能分享一下关于单元测试视图的经验吗?我看了很多关于如何使用视图进行单元测试的教程,但是每种方法都有一些缺点。
我找到了以下方法,它能正常工作,但我想知道是否有更好的方法。同时,也存在一些缺点,我稍后会解释。我也正在使用protractor进行E2E测试,但它们总是很慢,因此我将它们限制在最小范围内。
这是我的控制器。它有两个变量绑定到它的$scope上,这些变量在视图中使用:
// test_ctrl.js angular.module('app', []) .controller('TestCtrl', ["$rootScope", "$scope", function ($rootScope, $scope) { $scope.bar = "TEST"; $scope.jobs = [ {name: "cook"} ]; }]);
视图将$scope.bar放入一个``中,并将$scope.jobs数组放入一个`ng-repeat`指令中:
Bar is {{bar || "NOT SET"}}
- {{job.name}}
以下是测试代码:
describe('Controller: TestCtrl', function () { beforeEach(module('templates')); beforeEach(module('app')); var TestCtrl, $rootScope, $compile, createController, view, $scope; beforeEach(inject(function($controller, $templateCache, _$rootScope_, _$compile_, _$httpBackend_) { $rootScope = _$rootScope_; $scope = $rootScope.$new(); $compile = _$compile_; createController = function() { var html = $templateCache.get('views/test.html'); TestCtrl = $controller('TestCtrl', { $scope: $scope, $rootScope: $rootScope }); view = $compile(angular.element(html))($scope); $scope.$digest(); }; })); it('should test the view', function() { createController(); expect(view.find("li").length).toEqual(1) console.log($scope.jobs) }); });
在`beforeEach`函数中,我设置了控制器。`createController`函数(从测试代码中调用)从`$templateCache`中获取一个视图,使用自己的`$scope`创建一个控制器,然后编译模板并触发`$digest`。
模板缓存使用karma的预处理器ng-html2js填充:
// karma.conf.js ... preprocessors: { 'app/views/*.html': 'ng-html2js' } ...
使用这种方法,我遇到了一些问题,并有一些疑问:
1. ng-repeat在对象中添加了额外的$$hashKey键
我的测试中的`expect($scope.jobs).toEqual([{name: "cook"}]);`抛出了错误:
Expected [ { name : 'cook', $$hashKey : '009' } ] to equal [ { name : 'cook' } ]
我知道`ng-repeat`会添加这些键,但测试这个很傻。我能想到的唯一解决办法是分离控制器测试和视图测试。但是当我在控制器中检查`jobs`数组时,`$$hashKey`不存在。有什么想法,为什么会发生这种情况吗?
2. $scope问题
当我第一次尝试时,我只定义了一个本地作用域`$scope={}`,而不是像在其他控制器测试中那样使用`$scope = $rootScope.$new()`。但是,只有一个普通对象作为本地作用域时,我无法编译它(`$compile(angular.element(html))($scope);`会抛出错误)。
我也在考虑是否将`$rootScope`本身作为当前本地作用域传递给控制器是一个好方法。这是一个好的方法吗?或者还有我没有看到的任何缺点吗?
3. 最佳实践
我很想知道其他人是如何在AngularJS中进行单元测试的。我认为视图必须进行测试,因为在所有的angular指令中,它们中包含了很多逻辑,我很乐意看到它们得到完善;)