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

时间:2015-07-18 07:09:44

标签: javascript angularjs unit-testing jasmine angularjs-factory

我已经在使用AngularJS进行开发时已经有一段时间了,我写的内容有效,但我知道我想在AngularJS代码上运行单元测试。

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

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的承诺,以便在样式表嵌入页面时我可以运行其他逻辑。

现在,我使用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?
    });
  });
});

如何在页面中注入te服务并确保加载样式表?

编辑:加载服务现在有效:

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');
    });
});

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

非常感谢任何帮助。

亲切的问候

2 个答案:

答案 0 :(得分:1)

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

  

如果您想要这样做,我建议您将服务更改为directive,看看如何注入脚本元素,操纵DOM。这样你就可以一举两得,因为你需要注入$compile来测试你的指令(这将使你能够编译一个自定义的head元素来启动)。但这略微超过顶部"现在。

实现:

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

    link.onload = deferred.resolve;

    $document.head.append(link);

    return deferred.promise;
  }
}

beforeEach:

/**
 * 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。

答案 1 :(得分:0)

我刚才有这个疑问。 要将控制器和服务注入测试,您需要使用名为Angular Mocks的工具。这里有一些关于它的official reference

我觉得你和Karma环境一起使用它。

这是一本很棒的入门教程:

https://www.airpair.com/angularjs/posts/unit-testing-angularjs-applications

This other one适用于Ionic Framework,但仍可适用于您的情况

希望它可以提供帮助。