[英]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.