使用 angular.element('*[ng-app]').injector() 与业力 + 茉莉花



我有一个angular 1应用程序,我正在以非常自定义的风格编写它,因此切换到angular 2要直接得多,因此,例如,不使用angular.service()在angular中创建服务并使用依赖注入的常规方法,而是创建一个原始类型脚本(或ES2015风格)class。当在浏览器中正常运行时,以下所有代码都会在没有任何问题的情况下运行。

问题特别在于一行:

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

因果报应中的错误是:

Uncaught TypeError: Cannot read property 'get' of undefined

很自然,这意味着注射器没有被定位。同样,当在浏览器中正常运行时,这绝对可以100%工作。同样值得注意的是,这一行是在jQueryDOM就绪事件$(function{...}); 上发生的服务实例化时调用的

模块引导以使用<html ng-app="myApp">的常规文档方式完成。ng-app指令可以移动到<body>,因为应用程序不像以前那样需要<head>元素中的作用域。也许这就是因果报应被这个召唤窒息的原因。

更新:将ng-app移动到<body>没有产生任何变化

我已经浏览了一些有角度的mock源代码和.d.ts文件,试图找到任何其他方法来获得应用程序的注入器,但到目前为止还没有看到任何可以使用的方法。

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

不出所料,由于这是一种非常不典型的方法,谷歌的结果并没有太大帮助。

更新:

关于问题的更多上下文

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

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

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

你需要做的是猴子补丁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()声明之后,你就可以开始了!

我得到了同样的错误,并通过以下方法解决了这个问题。。。

注意:我使用的是Typescript

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元素的原型

最新更新