关键要点
link
函数负责核心逻辑实现,例如 DOM 操作和事件处理,应使用 AngularJS 的测试实用程序进行彻底测试。 $templateCache
中,可以测试模板中必要元素的正确应用和集成,从而简化测试过程。 单元测试是软件开发中不可或缺的一部分,它有助于减少代码错误。测试是提高代码质量的几项任务之一。 AngularJS 考虑到测试性而创建,因此在框架之上编写的任何代码都可以轻松测试。在我上一篇关于测试的文章中,我介绍了单元测试控制器、服务和提供程序。本文继续讨论指令测试。指令与其他组件不同,因为它们不是在 JavaScript 代码中用作对象,而是在应用程序的 HTML 模板中使用。我们编写指令来执行 DOM 操作,并且在单元测试中不能忽略它们,因为它们起着重要的作用。此外,它们直接影响应用程序的可用性。我建议您查看以前关于在 AngularJS 测试中模拟依赖项的文章,因为我们将在本文中使用该文章中的一些技术。如果您想试用本教程中开发的代码,可以查看我为您设置的 GitHub 存储库。
指令测试
指令是 AngularJS 中最重要和最复杂的组件。指令测试很棘手,因为它们不像函数那样被调用。在应用程序中,指令在 HTML 模板上声明性地应用。当模板被编译并且用户与指令交互时,它们的 action 就会被执行。执行单元测试时,我们需要自动化用户操作并手动编译 HTML 以测试指令的功能。
设置测试指令的对象
就像测试任何语言或使用任何框架中的任何逻辑片段一样,我们需要在开始测试指令之前获取所需对象的引用。此处要创建的关键对象是一个包含要测试的指令的元素。我们需要编译一个指定了指令的 HTML 片段才能使指令生效。例如,考虑以下指令:
angular.module('sampleDirectives', []).directive('firstDirective', function() { return function(scope, elem){ elem.append('This span is appended from directive.'); }; });
指令的生命周期将启动,并且将执行编译和链接函数。我们可以使用 $compile
服务手动编译任何 HTML 模板。以下 beforeEach
块编译上述指令:
angular.module('sampleDirectives', []).directive('firstDirective', function() { return function(scope, elem){ elem.append('This span is appended from directive.'); }; });
编译后,指令的生命周期将启动。在下一个 digest 周期之后,指令对象将处于与页面上显示相同的状态。如果指令依赖于任何服务来实现其功能,则必须在编译指令之前模拟这些服务,以便可以在测试中检查对任何服务方法的调用。我们将在下一节中看到一个示例。
测试链接函数
link
函数是指令定义对象 (DDO) 中最常用的属性。它包含指令的大部分核心逻辑。此逻辑包括简单的 DOM 操作、侦听发布/订阅事件、监视对象或属性的变化、调用服务、处理 UI 事件等等。我们将尝试涵盖大多数这些场景。
DOM 操作
让我们从上一节中定义的指令的案例开始。此指令将一个 span 元素添加到应用指令的元素的内容中。可以通过在指令内查找 span 来测试它。以下测试用例断言此行为:
var compile, scope, directiveElem; beforeEach(function(){ module('sampleDirectives'); inject(function($compile, $rootScope){ compile = $compile; scope = $rootScope.$new(); }); directiveElem = getCompiledElement(); }); function getCompiledElement(){ var element = angular.element('<div first-directive=""></div>'); var compiledElement = compile(element)(scope); scope.$digest(); return compiledElement; }
观察者
由于指令作用于作用域的当前状态,因此它们应该具有观察者,以便在作用域的状态发生变化时更新指令。观察者的单元测试必须操作数据并通过调用 $digest
来强制观察者运行,并且必须在 digest 周期之后检查指令的状态。以下代码是上述指令的略微修改版本。它使用作用域上的字段来绑定 span 内的文本:
it('should have span element', function () { var spanElement = directiveElem.find('span'); expect(spanElement).toBeDefined(); expect(spanElement.text()).toEqual('This span is appended from directive.'); });
测试此指令类似于第一个指令;除了它应该针对作用域上的数据进行验证,并且应该检查更新。以下测试用例验证指令的状态是否发生变化:
angular.module('sampleDirectives').directive('secondDirective', function(){ return function(scope, elem){ var spanElement = angular.element('' + scope.text + ''); elem.append(spanElement); scope.$watch('text', function(newVal, oldVal){ spanElement.text(newVal); }); }; });
相同的技术也可以用于测试属性上的观察者。
(后续内容由于篇幅限制,将简化并概括,保留核心测试方法和思路)
DOM 事件 可以使用 jqLite 的 triggerHandler
模拟点击事件并验证结果。
指令模板测试 使用 $templateCache
预加载模板,简化测试。
指令作用域测试 针对隔离作用域,验证属性绑定和方法调用。
require 测试 验证指令依赖关系,包括严格依赖和可选依赖。
replace 测试 检查指令元素是否被替换。
transclude 测试 验证指令是否正确处理 transcluded 内容。
总结
如本文所示,与 AngularJS 中的其他概念相比,指令更难测试。同时,它们也不能被忽略,因为它们控制着应用程序的一些重要部分。AngularJS 的测试生态系统使我们更容易测试项目的任何部分。我希望通过本教程,您现在对测试指令更有信心。请在评论部分告诉我您的想法。如果您想试用本教程中开发的代码,可以查看我为您设置的 GitHub 存储库。
(FAQs 部分由于篇幅过长,此处省略。核心内容已在上文涵盖。)
以上是AngularJS测试提示:测试指令的详细内容。更多信息请关注PHP中文网其他相关文章!