当使用"UpgradeModule"降级服务进行单元测试时,Angular 2:"Unknown Provider:$$ angularInjectorProvider"

Gre*_*obs 12 angularjs

我们的应用程序目前有大约4,500多个现有的Angular 1测试.我们现在正在使用Angular 2 UpgradeModule来降级Angular 2服务,该服务是从我们的应用程序的run()方法中使用的.这会导致所有测试失败并出现Error: [$injector:unpr] Unknown Provider $$angularInjectorProvider错误.

我创建了一个plnkr来演示这个问题(http://plnkr.co/edit/XuMYBr9xInqq18Kr6EAs?p=preview).

基本上Angular 1模块看起来像这样:

// angular1.module.ts

angular.module( 'testApp' )
    .run( [ 'Angular2Service', Angular2Service => {  // injecting downgraded service
        Angular2Service.showTestMessage();
    } ] );
Run Code Online (Sandbox Code Playgroud)

Angular2Service降级在哪里:

// app.module.ts

angular.module( 'testApp' )
    .factory( 'Angular2Service', downgradeInjectable( Angular2Service ) );


@NgModule({
    imports: [ BrowserModule, UpgradeModule ],
    providers : [ Angular2Service ]
})
export class AppModule {
    ngDoBootstrap() {}
}
Run Code Online (Sandbox Code Playgroud)

最初到目前为止,我'Angular2Service'在测试执行时遇到了一个Unknown Provider错误,所以我添加了一个beforeEach()编译所有内容AppModule:

beforeEach( async( () => {
    TestBed.configureTestingModule( {
        imports : [ AppModule ]
    } )
        .compileComponents();
} ) );
Run Code Online (Sandbox Code Playgroud)

这就是我遇到Error: [$injector:unpr] Unknown Provider $$angularInjectorProvider错误的地方.

正在执行的测试本身纯粹是一个Angular 1测试,如果我没有注入Angular2Servicerun()方法,它将通过:

describe( 'testComponent', () => {
    var $compile,
        $scope;

    beforeEach( module( 'testApp' ) );

    beforeEach( inject( $injector => {
        $compile = $injector.get( '$compile' );
        $scope = $injector.get( '$rootScope' ).$new();
    } ) );


    it( 'should show the text "Test Component" in the DOM', () => {
        var element = $compile( '<test-component></test-component>' )( $scope );
        $scope.$apply();

        expect( element[ 0 ].innerHTML ).toBe( 'Test Component' );
    } );

} );
Run Code Online (Sandbox Code Playgroud)

我希望这可以修复,以便我们所有的纯Angular 1测试可以继续不变,但如果需要我也可以更新它们.任何有关这方面的帮助将不胜感激!

http://plnkr.co/edit/XuMYBr9xInqq18Kr6EAs?p=preview

Yas*_*bee 5

我遇到了同样的问题,并提出了解决方案。这不是最好的方法,但是它只是解决了迁移阶段的问题。

我确定您使用的是upgrade-static.umd.jsdist文件而不是upgrade.umd.js。静态代码旨在与ngc AoT编译一起使用,我们应该在生产应用程序中使用它。如果您深入研究它的代码,就可以很容易地发现它定义了一个新的angularjs模块$$UpgradeModule,该模块注册了一个名为$$angularInjector(上面错误中的那个)值提供程序的$$angularInjector东西-这件事是负责将Angular模块注入angularjs中。

问题

您以前的angularjs测试不会启动,$$UpgradeModule因此其提供程序不可注入。请注意angular-mocks(定义了global moduleinjectfns)对茉莉花和mocka进行了一些修补,以在套件之间提供某种注入隔离。

解决方案

您只需module('$$UpgradeModule')在每次测试将直接(或间接)注入降级的提供程序的代码时,都在第一个before 调用。

但是,这不是那么简单:)。实际上$$UpgradeModule是在UpgradeModule.boorstrap函数中声明的。这意味着您需要在进行任何测试之前引导整个应用程序(angularjs和Angular)(或更严格的形式-引导根模块)。这不好,因为我们要完全隔离地测试模块和提供程序。

另一种解决方案

一种替代方法是使用中的UpgradeAdapter定义upgrade.umd.js。老实说,我没有尝试过-但是从代码看来,它可以仅启动我们想要的模块,而无需引导整个应用程序。但我认为我们可能需要使用UpgradeAdapter方法重新测试中的降级,以使事情正常进行。


编辑

例:

要进行引导,您需要在导入测试文件之前将应用程序模块导入为SystemJs。所以你karma-stest-shim.js会包含这样的东西

System.import('systemjs.config.js')
  .then(importSystemJsExtras)
  .then(importApp)
  .then(initTestBed)
  .then(initTesting);

function importApp() {
    return Promise.all(
        [
            System.import('app'),
        ]
    )
}
Run Code Online (Sandbox Code Playgroud)

这将对两个版本都进行常规引导并进行$$upgradeModule定义。

然后在将注入降级的提供程序的任何测试中

beforeEach(function () {
    // the ng1 module for the downgraded provider 
    module('services');
    // the trick is here
    module('$$UpgradeModule');
});
Run Code Online (Sandbox Code Playgroud)