javascript - 如何对 AngularJS 服务/工厂进行单元测试

标签 javascript angularjs unit-testing jasmine angularjs-factory

我已经使用 AngularJS 进行开发一段时间了,我写的东西很有效,但我知道我已经到了想要在我的 AngularJS 代码上运行单元测试的地步。

我创建了一个非常简单的服务,它将在页面上注入(inject)样式表, 请参阅下面的示例代码:

var OfficeSuiteStylesheetInjectorModule = angular.module('OfficeSuiteStylesheetInjectorModule', []);

OfficeSuiteStylesheetInjectorModule.factory('stylesheetInjectorService', ['$q', function($q) {
    // Returns the service itself.
    return {
        inject: function(id, uri) {
            var deferred = $q.defer();

            // Embed the stylesheet into the page, but only when it's non-existing.
            if (!angular.element('#' + id).length) {
                    var link = StylesheetFactory.Create(id, uri);
                    {
                        link.onload = deferred.resolve;
                        angular.element('head').append(link);
                    }

                    return deferred.promise;
                }
        }
    }
}]);

这不是一个大服务,它只是依赖于 $q 的 promise ,以便我可以在样式表嵌入到页面中时运行额外的逻辑。

现在,我正在使用 Jasmine(我对此还很陌生)来测试我的 JavaScript 代码,我想测试这个模块。

我有一个骨架:

// Tests for the angular 'StylesheetInjectorService'.
describe('StylesheetInjectorService', function() {
    var stylesheetInjectorService = {};

    // This code is executed before every test.
    beforeEach(function() {
        // Tells jamine that the module we're working on is the 'OfficeSuiteStylesheetInjectorModule'.
        angular.module('OfficeSuiteStylesheetInjectorModule');
    });

    // Ensures that it injects a stylesheet element into the page.
    it('Should inject a stylesheet element into the page.', function() {
        // How to test here that the stylesheet is injected?
    });
  });
});

如何在页面中注入(inject)服务并确保样式表已加载?

编辑:加载服务现在可以运行:

beforeEach(module('OfficeSuiteStylesheetInjectorModule'));

// This code is executed before every test.
beforeEach(function() {

    // Inject the required dependencies into the page.
    inject(function($injector) {
        stylesheetInjectorService = $injector.get('stylesheetInjectorService');
    });
});

但是同样的问题仍然悬而未决。如何测试页面中是否嵌入了样式表?

非常感谢任何帮助。

亲切的问候

最佳答案

要编写将样式表附加到 angular.element('head') 的规范,我会稍微更改逻辑以将其附加到 $document.head >。

If you dont want to do that, I would recommend that you change your service into a directive seeing as how injecting a script element, is manipulating the DOM. That way you would kill two birds with one stone, as you would need to inject $compile to test your directive (which would enable you to $compile a custom head element to boot). But this is slightly "over the top" for now.

实现:

if (!angular.element('#' + id).length) {
  var link = StylesheetFactory.Create(id, uri);

    link.onload = deferred.resolve;

    $document.head.append(link);

    return deferred.promise;
  }
}

之前:

/**
 * Sorry, this was previously $location which was just 
 * such a silly mistake.
 */
var $timeout; 

beforeEach(function () {
  inject(function ($injector) {
    $timeout = $injector.get('$timeout');
  });
});

它:

it('attaches the stylesheet to $document.head', function () {
  styleSheetInjectorService.inject('someId', '/path/to/some/stylesheet');
  $timeout.flush(); // flush promises
  expect(angular.element($document.head).lastChild[0].nodeName).to.eq('LINK');
});

按照这些思路应该可以让您启动并运行。请记住,我编写的规范使用 chai#expect风格断言,以及 mocha测试框架。如果您打算复制粘贴,请编辑语法以适合 Jasmine。

关于javascript - 如何对 AngularJS 服务/工厂进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31488763/

相关文章:

javascript - NW.js - PouchDB - 无法通过 Node Webkit 中的 require() 使用 PouchDB

angularjs - 混合移动应用程序的数据库解决方案

maven - 跳过 Maven 中某些模块的测试

java - 是否需要测试公共(public)内部类?

python - 如何为 Python 单元测试提供标准输入、文件和环境变量输入?

javascript - 如何在 for 循环内将新项目附加到同一数组中的同一索引

javascript - Lifecycle React组件,具有即时加载组件

javascript只返回字符串的一级域名

javascript - 从 Angular Directive(指令)获取数据

angularjs - 测试来自 Controller 调用的服务的广播