【发布时间】:2014-07-25 16:37:33
【问题描述】:
我在为我的一些 Angular 指令编写单元测试时遇到问题。特别是那些在指令中使用 jQuery 的。我在下面设计了一个最小的示例来说明我的问题。
这个愚蠢的指令将点击事件绑定到元素。单击时,它会隐藏元素。 According to Angular,传递给指令的元素将被包装为 jQuery 元素。如果 jQuery 可用,它将使用 jQuery,否则将使用 Angular 的 jQuery Lite。事实上,如果我在包含 jQuery 的浏览器中使用该指令,该指令将起作用并隐藏被点击的元素。
angular.module('myApp').directive('clickhide', function() { return {
link: function(scope, element, attrs) {
element.bind('click', function(e) {
element.hide();
scope.$digest();
});
}
}});
这是该指令的 Karma 单元测试规范:
describe('clickhide', function() {
var scope, elm;
beforeEach(module('MyApp'));
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope;
elm = angular.element('<div clickhide></div>');
$compile(elm)(scope);
scope.$digest();
}));
it('should do a click', function() {
elm[0].click();
//OOPS: undefined is not a function error
expect($(elm).find(":hidden").length).toBe(1);
});
});
当我运行这个测试时,它失败并出现“未定义不是函数”的错误,这意味着没有加载 jQuery,而 Angular 使用了 jQuery Lite,它没有定义 hide()。
我找到了两种解决此问题的方法。
不要使用 jQuery。需要重写我不想做的指令。
在我的指令中显式包装元素以使其成为 jQuery 元素:
$(element).hide()。还需要修改我的指令,我不想这样做。如果没有其他选择,我当然可以这样做。
我觉得应该可以让 Angular 在进行单元测试时自动在指令中使用 jQuery,就像在 Web 浏览器中使用一样。我相信关键点是 Angular 文档中的这一行:
要使用 jQuery,只需在 DOMContentLoaded 事件触发之前加载它。
我不清楚在运行单元测试时何时发生 DOMContentLoaded。我的 Karma 配置文件包含 jQuery 作为第一个文件,在 angular 之前:
module.exports = function(config) {
config.set({
basePath: '../../',
frameworks: ['jasmine', 'ng-scenario'],
files: [
'app/bower_components/jquery/dist/jquery.min.js',
'app/bower_components/angular/angular.js',
'app/bower_components/angular-route/angular-route.js',
'app/bower_components/angular-sanitize/angular-sanitize.js',
'app/bower_components/angular-mocks/angular-mocks.js',
...
],
exclude: [],
reporters: ['progress'],
port: 9876,
runnerPort: 9100,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
captureTimeout: 60000,
singleRun: false
});
};
我需要在测试中注入 jQuery 吗?也许这是业力的限制?有人知道吗?
【问题讨论】:
-
你能试试
expect(elm.find(":hidden").length).toBe(1);吗? -
它甚至没有到达那一行,因为由于我描述的事情,它在上面的行上有一个错误。
-
哦,好的。您是如何尝试在您的应用中加载 jQuery 的?
-
在我的业力配置文件中,我将 jQuery 作为“文件”部分的第一个文件加载,并且 jQuery 可以工作。它加载。但由于某种原因,Angular 仍然使用 jQuery Lite 作为默认的元素包装器。
-
还没有。我想但还没有太努力去弄清楚。同时,我使用集成测试(量角器)来覆盖我的指令。
标签: javascript jquery angularjs unit-testing karma-runner