Angular testing 遇到 Dynamic Component Loader的問題。

問題起因:

由於在Angular 的專案中開始使用 Dynamic Component Loader 來做一些頁面裡嵌入已經撰寫好、會重複使用的 component。但是在測試的時候反而遇到問題。


我測試的頁面只是一個很簡單的登入頁面,但是我的作法是 Lobby 頁面嵌入Login component而不是把Login整個寫在 Lobby裡面,由於使用Dynamic Component Loader就可以在使用者點擊『登入』時就把頁面中間載入Login component,點擊『註冊』時就載入Register component。

示意圖:


環境設定:

Ubuntu:   18.04.1 LTS

Angular Cli: 7.0.1

說明:

在Lobby component 中我在OnInit 中預設載入Login畫面,避免Lobby的內容區空空。
接著lobby.component.spec.ts 這支測試檔中主要程式碼如下:


describe('LobbyComponent', () => { let component: LobbyComponent; let fixture: ComponentFixture<LobbyComponent>;
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ LobbyComponent, LoginComponent, GeneralRegisterComponent ], imports: [ ReactiveFormsModule ], providers: [ DynamicComponentService, ChangeMainContService ], entryComponents: [ LoginComponent, GeneralRegisterComponent, ] }) .compileComponents(); }));
beforeEach(() => { fixture = TestBed.createComponent(LobbyComponent); component = fixture.componentInstance; fixture.detectChanges(); });
it('should create', () => { expect(component).toBeTruthy(); });
it('should see login component in lobby page', async(() => { const lobbyComp = TestBed.createComponent(LobbyComponent); lobbyComp.detectChanges(); const compiled = lobbyComp.debugElement.nativeElement; expect(compiled.querySelector('#loginComp')).toBeTruthy(); })); });


這邊大概說明一下由於使用Dynamic Component Loader要在你的@NgModule內加入 entryComponents: [] 讓loader 知道要載入哪些Components。所以很理所當然在測試檔中生成測試module的 TestBed.configureTestingModule({}) 加入entryComponents的內容。

不過加上去之後跑ng test的時候就會出現下面的錯誤。而且vscode在你填入那段程式的時候就已經幫你畫下紅線跟你說有問題。

ng cli 錯誤資訊:



瀏覽器的錯誤資訊:

明明加了entryCompnents但是好像不認得!最後在Overflow上面可以使用overriderModule的方式改寫TestBed.configureTestingModule()的內容,但是這邊記得要

import { BrowserDynamicTestingModule }  '@angular/platform-browser-dynamic/testing'

另一種寫法我比較喜歡😅 就是把要TestBed要產生的Testing Module 獨立寫在上方的NgModule內,程式碼就會變成如下:


@NgModule({     declarations: [         LobbyComponent,         LoginComponent,         GeneralRegisterComponent,     ],     imports: [         ReactiveFormsModule     ],     providers: [         DynamicComponentService,         ChangeMainContService     ],     entryComponents: [         LoginComponent,         GeneralRegisterComponent     ] }) class FakeEntryComponents { }
describe('LobbyComponent', () => {     let component: LobbyComponent;     let fixture: ComponentFixture<LobbyComponent>;
    beforeEach(async(() => {         TestBed.configureTestingModule({             imports: [                 FakeEntryComponents             ]         })        .compileComponents();     }));
    beforeEach(() => {         fixture = TestBed.createComponent(LobbyComponent);         component = fixture.componentInstance;         fixture.detectChanges();     });
    it('should create', () => {         expect(component).toBeTruthy();     });
    it('should see login component in lobby page', async(() => {         const lobbyComp = TestBed.createComponent(LobbyComponent);         lobbyComp.detectChanges();         const compiled = lobbyComp.debugElement.nativeElement;<         expect(compiled.querySelector('#loginComp')).toBeTruthy();     })); });

這樣比較清楚有架構而且測試檔也能正常執行。

REF:


留言