Angularjs 使用$location和$routeParams等依赖项测试Angular指令
这个问题有点与我有关。但是我想不出来。事情是这样的: 我有一个简单的角度指令,用于使用几个参数渲染应用程序的头部部分。一个通过,两个来自URL vie$location和$routeParam。该指令如下所示:Angularjs 使用$location和$routeParams等依赖项测试Angular指令,angularjs,testing,angularjs-directive,jasmine,karma-runner,Angularjs,Testing,Angularjs Directive,Jasmine,Karma Runner,这个问题有点与我有关。但是我想不出来。事情是这样的: 我有一个简单的角度指令,用于使用几个参数渲染应用程序的头部部分。一个通过,两个来自URL vie$location和$routeParam。该指令如下所示: 'use strict'; myApp.directive('appHeader', ['$routeParams', '$location', function ($routeParams, $location) { return { restrict:
'use strict';
myApp.directive('appHeader', ['$routeParams', '$location', function ($routeParams, $location) {
return {
restrict: 'E',
templateUrl: 'path/to/partials/template.html',
scope: {
icon: '@icon'
},
link: function (scope, element, attributes) {
var lastUrlPart = $location.path().split('/').pop();
scope.project = $routeParams.itemName;
scope.context = lastUrlPart === scope.project ? '' : lastUrlPart;
}
};
}]);
var LocationMock = function (initialPath) {
var pathStr = initialPath || '/project/bar';
this.path = function (pathArg) {
return pathArg ? pathStr = pathArg : pathStr;
};
};
spyOn(location, 'path').andCallFake(new LocationMock().path);
var viewTemplate = '<div>' +
'<div id="project">{{project}}</div>' +
'</div>';
beforeEach(inject(function ($templateCache) {
$templateCache.put('path/to/partials/template.html', viewTemplate);
}));
这是通过
调用的
现在我想添加一些测试。至于模板渲染,我已经完成了。下面的工作与预期的一样。考试通过了
describe('appHeader', function () {
var element, scope;
beforeEach(module('myApp'));
beforeEach(module('myAppPartials'));
beforeEach(inject(function ($rootScope, $compile) {
element = angular.element('<app-header icon="foo"></app-header>');
scope = $rootScope;
$compile(element)(scope);
scope.$digest();
}));
it('should contain the glyphicon passed to the directive', function () {
expect(element.find('h1').find('.glyphicon').hasClass('glyphicon-foo')).toBeTruthy();
});
});
但在我的测试中
it('should set scope.project to itemName from $routeParams', function () {
expect(scope.project).toEqual('foo');
});
范围。项目
未定义:
Running "karma:unit:run" (karma) task
Chrome 35.0.1916 (Mac OS X 10.9.3) appHeader should set scope.project to itemName from routeParams FAILED
Expected undefined to equal 'foo'.
Error: Expected undefined to equal 'foo'.
至于位置依赖性,我尝试设置一个模拟mysel,如下所示:
'use strict';
myApp.directive('appHeader', ['$routeParams', '$location', function ($routeParams, $location) {
return {
restrict: 'E',
templateUrl: 'path/to/partials/template.html',
scope: {
icon: '@icon'
},
link: function (scope, element, attributes) {
var lastUrlPart = $location.path().split('/').pop();
scope.project = $routeParams.itemName;
scope.context = lastUrlPart === scope.project ? '' : lastUrlPart;
}
};
}]);
var LocationMock = function (initialPath) {
var pathStr = initialPath || '/project/bar';
this.path = function (pathArg) {
return pathArg ? pathStr = pathArg : pathStr;
};
};
spyOn(location, 'path').andCallFake(new LocationMock().path);
var viewTemplate = '<div>' +
'<div id="project">{{project}}</div>' +
'</div>';
beforeEach(inject(function ($templateCache) {
$templateCache.put('path/to/partials/template.html', viewTemplate);
}));
然后在每个之前的中注入$location,并为path()的调用设置一个间谍,如下所示:
'use strict';
myApp.directive('appHeader', ['$routeParams', '$location', function ($routeParams, $location) {
return {
restrict: 'E',
templateUrl: 'path/to/partials/template.html',
scope: {
icon: '@icon'
},
link: function (scope, element, attributes) {
var lastUrlPart = $location.path().split('/').pop();
scope.project = $routeParams.itemName;
scope.context = lastUrlPart === scope.project ? '' : lastUrlPart;
}
};
}]);
var LocationMock = function (initialPath) {
var pathStr = initialPath || '/project/bar';
this.path = function (pathArg) {
return pathArg ? pathStr = pathArg : pathStr;
};
};
spyOn(location, 'path').andCallFake(new LocationMock().path);
var viewTemplate = '<div>' +
'<div id="project">{{project}}</div>' +
'</div>';
beforeEach(inject(function ($templateCache) {
$templateCache.put('path/to/partials/template.html', viewTemplate);
}));
但是,scope.context也没有定义
it('should set scope.context to last part of URL', function () {
expect(scope.context).toEqual('bar');
});
有人能指出我做错了什么吗?提供商的模拟工作正常,但问题出在范围内。您的指令具有独立的作用域。因此,该指令的范围是测试中定义的范围的子级。快速但不推荐的修复方法是:
it('should set scope.project to itemName from $routeParams', function () {
expect(scope.$$childHead.project).toEqual('foo'); });
测试指令时尽量避免使用范围。更好的方法是模拟模板并检查其中的数据。对于您的情况,它将是这样的:
'use strict';
myApp.directive('appHeader', ['$routeParams', '$location', function ($routeParams, $location) {
return {
restrict: 'E',
templateUrl: 'path/to/partials/template.html',
scope: {
icon: '@icon'
},
link: function (scope, element, attributes) {
var lastUrlPart = $location.path().split('/').pop();
scope.project = $routeParams.itemName;
scope.context = lastUrlPart === scope.project ? '' : lastUrlPart;
}
};
}]);
var LocationMock = function (initialPath) {
var pathStr = initialPath || '/project/bar';
this.path = function (pathArg) {
return pathArg ? pathStr = pathArg : pathStr;
};
};
spyOn(location, 'path').andCallFake(new LocationMock().path);
var viewTemplate = '<div>' +
'<div id="project">{{project}}</div>' +
'</div>';
beforeEach(inject(function ($templateCache) {
$templateCache.put('path/to/partials/template.html', viewTemplate);
}));
对于上下文,它将是相同的。谢谢你,这很有帮助。当涉及到指令中的范围时,我在控制器上下文中考虑得太多了。同时,我已经计算出元素中上下文和项目的每个实例都像预期的那样被填充。