簡體   English   中英

角度測試:TestBed不需要提供ApplicationRef

[英]Angular Testing: TestBed doesn't require providing ApplicationRef

我遵循https://angular.io/guide/testing為應用程序編寫測試的官方“測試”指南。

在測試具有依賴項的服務時,我需要為這些依賴項提供模擬,但有趣的是,這對於ApplicationRef似乎並不正確,我真的很想知道為什么。

該服務是這樣的:

export class MyService {

    constructor(
        private dependentService: DependentService,
        private applicationRef:ApplicationRef
    ){}
    ...

以及相應的測試規格:

describe('MyService', () => {
    let dependentServiceSpy: jasmine.SpyObj<HttpClient>;

    beforeEach(() => {
        const dependentServiceSpy = jasmine.createSpyObj('DependentService', ['test']);

        TestBed.configureTestingModule({
            // Provide both the service-to-test and its (spy) dependency
            // why is 'ApplicationRef' not needed here?? 
            providers: [
                MyService,
                { provide: DependentService, useValue: dependentService_spy }
            ]
        });
    });
    ...   

});

由於在MyService構造函數中同時注入了'DependentService'和'ApplicationRef',因此我希望在TestBed的providers數組中都需要它們。 但是,盡管忽略了“ DependentService”, 在測試中會產生錯誤, 而缺少的“ ApplicationRef”則不會

有合理的解釋嗎?

每個使用TestBed的Angular測試配置都從以下初始化開始:

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

Angular測試環境將使用BrowserDynamicTestingModule構造注射器,因為它適用於普通Angular模塊(另請參見https://blog.angularindepth.com/angular-dependency-injection-and-tree-shakeable-tokens-4588a8f70d5d )。

Angular合並BrowserDynamicTestingModule包含的提供程序。 該模塊聲明如下:

@NgModule({
  exports: [BrowserTestingModule],
  providers: [
    {provide: TestComponentRenderer, useClass: DOMTestComponentRenderer},
  ]
})
export class BrowserDynamicTestingModule {
}

BrowserTestingModule如下所示:

                /\
                ||

@NgModule({
  exports: [BrowserModule],
  providers: [
    {provide: APP_ID, useValue: 'a'},
    ELEMENT_PROBE_PROVIDERS,
    {provide: NgZone, useFactory: createNgZone},
  ]
})
export class BrowserTestingModule {
}

BrowserModule是:

                /\
                ||             

@NgModule({providers: BROWSER_MODULE_PROVIDERS, exports: [CommonModule, ApplicationModule]})
export class BrowserModule {
  ...
}

最后, ApplicationModule聲明ApplicationRef

                 /\
                 ||

export const APPLICATION_MODULE_PROVIDERS: StaticProvider[] = [
  {
    provide: ApplicationRef,
    useClass: ApplicationRef,
    deps:
        [NgZone, Console, Injector, ErrorHandler, ComponentFactoryResolver, ApplicationInitStatus]
  },
  ...
];


@NgModule({providers: APPLICATION_MODULE_PROVIDERS})
export class ApplicationModule {
  // Inject ApplicationRef to make it eager...
  constructor(appRef: ApplicationRef) {}
}

如您所見, ApplicationRef提供程序也已被實例化。

這樣,這里就沒有魔力了,Angular只會使用相同的算法,就像它將解析用戶定義的NgModules中的提供者一樣

我不得不猜測,但我認為:

每個組件都隱式包含更改檢測。 如果不是,則不會進行自動更改檢測。 但是要直接在代碼中使用此功能,必須在構造函數中顯式“捕獲”該服務。

現在,我們的TestBed將創建您在此處明確定義的服務。 但是它還將創建所有這些內部需要的服務(例如ChangeDetection,請參見經典的“ fixture.detectChanges()”)。 因此,您不必顯式創建它。

您提到的“ DependentService”不是內部Angular魔術的一部分,因此必須在TestBed中明確命名它。

溫暖的問候

那可能是因為,我們在constructor內部注入了ApplicationRef卻沒有在任何地方提供它。 那是一個普通的interface但是不是provider 我們僅在測試providers數組中提供提供providers而不是我們已經注入的所有providers 對於ChangeDetectorRef也是如此。 我們從不在提供程序內部providers數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM