了解AngularJS中app和测试中的注入依赖性

时间:2014-04-10 10:34:51

标签: javascript angularjs testing dependency-injection karma-runner

我在测试指令时遇到依赖注入(理解)问题(只有在有待处理请求时才会显示AjaxLoader)。

应用声明:

angular.module('app', [
    'directives.ajaxLoader',
    'services.httpRequestTracker',
    [...]
])

指令代码:

angular.module('directives.ajaxLoader', [])
.directive('ajaxLoader', ['httpRequestTracker',
    function(httpRequestTracker) {
        return {
            templateUrl: 'common/ajaxLoader.tpl.html',
            link: function($scope) { // This function can have more parameters after $scope, $element, $attrs, $controller
                $scope.hasPendingRequests = function() {
                    return httpRequestTracker.hasPendingRequests();
                };
            }
        };
    }
])

测试代码:

describe('ajaxLoader', function() {

    beforeEach(function() {
        module('directives.ajaxLoader', 'common/ajaxLoader.tpl.html');
    });

    describe('ajaxLoader directive', function() {});
});

从那里开始,我的指令在浏览器中运行得非常好,但测试失败并出现如下错误:

  

错误:[$ injector:unpr]未知提供者:httpRequestTrackerProvider   < - httpRequestTracker< - ajaxLoaderDirective

好的,所以我需要在某处注入我的依赖。我有两个解决方案:

    直接在我的指令中
angular.module('directives.ajaxLoader', [
     'services.httpRequestTracker'
])
  • 直接在我的测试代码中:
beforeEach(function() {
     module('directives.ajaxLoader', 'common/ajaxLoader.tpl.html', 'services.httpRequestTracker');
});

两者都有效,但我不明白哪一个更好,为什么?为什么它从一开始就在我的浏览器中工作而在我的测试中失败?在这两种情况下,我的所有指令和跟踪器都在我的主应用声明中注入

由于

1 个答案:

答案 0 :(得分:1)

加载模块

它适用于您的应用程序,因为已加载services.httpRequestTracker。你通过将其声明为主应用程序模块(您的第一个代码段)的依赖项来实现这一点。

然而,当你测试时,你想要模拟未经测试的所有内容以避免biass。在您的情况下,如果您在services.httpRequestTracker中遇到问题该怎么办? ajaxLoader可能没问题但你的测试会失败。

<强>嘲讽

要模仿其他所有内容,您有两种选择:

要使用依赖项,您必须使用module()加载模块。

你必须加载依赖项,但这可能有一个模拟实现。

依赖注入

依赖注入允许您解耦类。有一个服务定位器可以按名称解析依赖关系。也就是说,你说C类的属性a的类型是'animal'(一个字符串!)。角度核心中的服务定位器查找哪个组件实现它。确定这一点的方法是查找加载的模块(例如主应用程序模块的依赖关系)。

您没有在测试区域中定义任何此类内容(但这不是问题!)。 Karma使用包含要使用的文件列表的文件karma.conf。您可以使用此文件添加库或模拟组件。

针对您的特定问题:

该指令取决于httpRequestTracker。如果你不在那里注射它,它将无法工作(所以没关系)。 在您的测试中,您必须加载两者。这就是为什么第一次失败而第二次失败的原因。但是,我没有加载httpRequestTracker,而是加载了它的模拟实现。