关键要点
$scope
上的 $emit/$broadcast
事件提供事件聚合,允许对象即使彼此不知道也能相互交互。单元测试是隔离编写的,因此测试规范需要模拟一端来测试功能。angular-mocks
库包含 ngAnimateMock
模块来简化此过程。AngularJS 会阻止动画运行,直到第一个 digest 循环完成,以加快初始绑定速度。在构建和交付功能齐全的软件的过程中,我们应用多种技术来检查软件的正确性和质量。单元测试就是其中一种技术。许多组织非常重视单元测试,因为它降低了查找和修复应用程序潜在问题的成本。当我们开始开发包含数十万行 JavaScript 代码的应用程序时,我们就无法避免测试代码。一些 JavaScript 开发人员表示,测试 JavaScript 更加重要,因为在运行时之前,语言的行为是未知的。值得庆幸的是,AngularJS 通过支持依赖注入 (DI) 等特性,使使用该框架编写的代码测试更容易。在我之前的几篇文章中,我讨论了关于模拟的一些技巧,如何测试控制器、服务和提供程序以及如何测试指令。本文将介绍测试 AngularJS 应用程序的引导块(包括配置块、运行块和路由解析块)、作用域事件和动画。您可以从我们的 GitHub 存储库下载本文中使用的代码,您还可以在其中找到运行测试的说明。
测试配置和运行块
配置和运行块在模块生命周期的开始执行。它们包含控制模块、小部件或应用程序工作方式的重要逻辑。测试它们有点棘手,因为它们不能像其他组件一样直接调用。同时,它们也不能被忽略,因为它们的作用至关重要。考虑以下配置和运行块:
angular.module('configAndRunBlocks', ['ngRoute']) .config(function ($routeProvider) { $routeProvider.when('/home', { templateUrl: 'home.html', controller: 'HomeController', resolve: { bootstrap: ['$q', function ($q) { return $q.when({ prop: 'value' }); }] } }) .when('/details/:id', { templateUrl: 'details.html', controller: 'DetailsController' }) .otherwise({ redirectTo: '/home' }); }) .run(function ($rootScope, messenger) { messenger.send('Bootstrapping application'); $rootScope.$on('$locationChangeStart', function (event, next, current) { messenger.send('Changing route to ' + next + ' from ' + current); }); });
与测试提供程序的情况类似,我们需要确保在测试配置和运行块中的功能之前加载模块。因此,我们将使用一个空的注入块来加载模块。以下代码片段模拟了上述块中使用的依赖项并加载了模块:
describe('config and run blocks', function () { var routeProvider, messenger; beforeEach(function () { module('ngRoute'); module(function ($provide, $routeProvider) { routeProvider = $routeProvider; spyOn(routeProvider, 'when').andCallThrough(); spyOn(routeProvider, 'otherwise').andCallThrough(); messenger = { send: jasmine.createSpy('send') }; $provide.value('messenger', messenger); }); module('configAndRunBlocks'); }); beforeEach(inject()); });
我故意没有模拟 $routeProvider
对象,因为我们稍后将在本文中测试已注册的路由。现在模块已加载,配置和运行块已执行。因此,我们可以开始测试它们的行为。由于配置块注册路由,我们可以检查它是否注册了正确的路由。我们将测试是否注册了预期的路由数量。以下测试验证配置块的功能:
describe('config block tests', function () { it('should have called registered 2 routes', function () { //Otherwise internally calls when. So, call count of when has to be 3 expect(routeProvider.when.callCount).toBe(3); }); it('should have registered a default route', function () { expect(routeProvider.otherwise).toHaveBeenCalled(); }); });
示例代码中的运行块调用一个服务并注册一个事件。我们将在本文后面测试该事件。目前,让我们测试对服务方法的调用:
describe('run block tests', function () { var rootScope; beforeEach(inject(function ($rootScope) { rootScope = $rootScope; })); it('should send application bootstrap message', function () { expect(messenger.send).toHaveBeenCalled(); expect(messenger.send).toHaveBeenCalledWith("Bootstrapping application"); }); });
(后续部分关于测试作用域事件、路由、解析块和动画的描述,由于篇幅限制,此处省略。 完整的测试代码示例可以参考原文GitHub仓库)
结论
通过这篇文章,我介绍了过去两年在测试 AngularJS 代码时学习到的大部分测试技巧。这并非结束,当您为实际应用程序的业务场景编写测试时,您将学到更多。我希望您现在已经对测试 AngularJS 代码有了足够的了解。为什么还要等待?立即为到目前为止编写的每一行代码编写测试!
(原文中FAQs部分也由于篇幅限制省略)
以上是AngularJS测试:引导程序块,路线,事件和动画的详细内容。更多信息请关注PHP中文网其他相关文章!