使用angular.element('* [ng-app]')。injector()与karma + jasmine

时间:2015-11-19 01:52:12

标签: angularjs dependency-injection karma-jasmine

我有一个角度1的应用程序,我正在以非常自定义的方式编写,因此切换到角度2更直接,所以例如,不使用angular.service()在角度和使用中创建服务正常的依赖注入方式,而是创建原始打字稿(或ES2015样式)class。在浏览器中正常运行时,所有以下代码都会运行,没有任何问题。

问题在于特别是一行:

Auth.jwtHelper = angular.element('*[ng-app]').injector().get('jwtHelper');

业力中引发的错误是:

Uncaught TypeError: Cannot read property 'get' of undefined

很自然地意味着没有找到注射器。同样,在浏览器中正常运行时,这绝对可以100%运行。另外值得注意的是,在jQuery DOM就绪事件$(function{...});上发生的服务实例化时会调用此行

模块引导以正常记录的方式使用<html ng-app="myApp">完成ng-app指令可以移动到<body>,因为应用程序不需要<head>中的范围像以前一样。也许这就是为什么业力因此而窒息。

更新:将ng-app移至<body>未产生任何变更

我已经挖掘了一些角度模拟源代码和.d.ts文件,试图找到任何替代方法来获取应用程序的注入器,但还没有看到我可以使用的任何东西。

我正在寻找的是建设性的建议,不需要使用角度的典型注入模式的替代方案,或任何其他可能有用的花絮。

正如预期的那样,由于这是一种非常典型的方法,因此谷歌搜索结果并不是很有帮助。

更新

关于这个问题的更多背景信息

export class Auth{
    public static jwtHelper;

    public static init(){
        Auth.jwtHelper = angular.element('*[ng-app]').injector().get('jwtHelper');
    }
}
$(Auth.init);

正如您在这里看到的那样,init方法在DOM就绪时调用,而不是从单元测试调用。我无法提供单元测试的描述块,因为它与我的单元测试分开运行。它是应用程序加载的一部分。

2 个答案:

答案 0 :(得分:2)

我意识到这是一个非常古老的问题,但看到我刚遇到同样的问题,我想我会在那里为下一个人发布我的解决方案。

你需要做的是猴子补丁angular.element所以它返回注射器:

beforeEach(angular.mock.inject(['$injector', function(injector) {
  // save original
  var original = angular.element;

  // replace with our own
  angular.element = function() {
    // proxy all calls to the original
    var result = original.apply(this, arguments);

    // add the injector to the result
    result.injector = function() { return injector; };
    return result;
  }

  // also add all the angular.element properties to our fake or some other stuff will break
  for (let prop in original) {
    angular.element[prop] = original[prop];
  }
}]));

在您的规格中angular.mock.module()声明后立即放置该位,您就可以了!

答案 1 :(得分:0)

我遇到了相同的错误,并可以通过以下解决此问题...

注意:我正在使用打字稿

let SampleController, $injector;

(<any>angular).mock.inject(($componentController, _$injector_) => {
     $injector = _$injector_;

     // angular.element(document.body).injector() doesn't behave correctly because we don't have ng-app in the DOM for unit tests. Spy the injector response instead.
     spyOn(angular.element.prototype, "injector").and.callFake(() => {
         return $injector;
     });

     // angular.element is triggered in the super of SampleController
     SampleController = $componentController("SampleComponent", null);
});

我认为这要简单一些,因为您专注于angular.element的原型