前言
同樣是元件的測試,這次試著假設一些不同的狀況,練習如何對這些元件進行測試。
元件的繫結 (一) - 內嵌繫結
建立一個 BannerComponent 並且透過繫結到元件的 title
屬性來展示動態標題。
輸入 ng g c banner -m app
產生 BannerComponent 並且於 app.module 內註冊。
class
1 | import { Component, OnInit } from '@angular/core'; |
Template
1 | <h1>{{title}}</h1> |
app.component
1 | <app-banner></app-banner> |
將會寫一系列測試來探查 h1 標籤的值。
banner.component.spec
首先在 beforeEach() 中使用標準的 HTML querySelector 來找到該元素。
1 | describe('BannerComponent', () => { |
測試看看!
createComponent() 函式不會繫結資料,因為繫結是在 Angular 執行變更檢測時才發生的。
解法 - 補上 detectChanges()
TestBed.createComponent 不能觸發變更檢測,所以要補上 detectChanges() 。
透過呼叫 fixture.detectChanges() 來要求 TestBed 執行資料繫結。
1 | it('最終呈現在網頁上的標題文字是否與元件內 title 屬性的值相同', () => { |
這種變更檢測是故意設計的,它給了測試者一個機會:
- 在 Angular 初始化資料繫結以及呼叫生命週期的鉤子之前探查並改變元件的狀態
像是我們可以這麼做:
1 | it('最終呈現在網頁上的標題文字是否與元件內 title 屬性的值相同', () => { |
在呼叫 fixture.detectChanges() 之前修改元件的 title 屬性。
自動變更檢測
BannerComponent 的這些測試需要頻繁呼叫 detectChanges() ,而 Angular 測試環境可以做到自動執行變更檢測,如:
1 | describe('BannerComponent', () => { |
第一個測試的例子展示了自動 detectChanges() 的好處。
第二、三個例子要說明的是,Angular 測試環境不會知道測試程式改變了元件的 title
屬性。
自動檢測只對非同步行為比如承諾的解析、計時器和 DOM 事件作出反應,直接修改元件屬性值是不會觸發自動檢測的。
測試程式必須手動呼叫 detectChange(),來觸發新一輪的變更檢測週期。
元件的繫結 (二) - 模擬使用者輸入
修改剛剛的範例,替這個元件增加一個 Input 輸入,根據輸入來變化標題。
banner Template
1 | <h1>{{title}}</h1> |
接著需要到 app.module 內 import FormsModule
才可以使用雙向繫結。
使用 dispatchEvent() 修改輸入值
如果想在測試時模擬使用者輸入,你就要找到 input 元素並設定它的 value 屬性。
而 Angular 不知道我們設定了 input 元素的 value 屬性,所以需要先呼叫:
- dispatchEvent()
- 再呼叫 detectChanges()
最後別忘了同樣也必須在 TestBed.configureTestingModule 內 import FormsModule
。
1 | describe('BannerComponent', () => { |