Angular 測(cè)試工具API

2022-07-08 09:41 更新

測(cè)試實(shí)用工具 API

本頁(yè)面描述了一些最有用的 Angular 測(cè)試特性。

Angular 測(cè)試實(shí)用工具包括 ?TestBed?、?ComponentFixture ?以及一些控制測(cè)試環(huán)境的函數(shù)。?TestBed ?和 ?ComponentFixture ?類是單獨(dú)介紹的。

下面是一些獨(dú)立函數(shù)的摘要,以使用頻率排序:

函數(shù)

詳情

waitForAsync

在一個(gè)特殊的async 測(cè)試區(qū)域中運(yùn)行測(cè)試(?it?)的函數(shù)體或準(zhǔn)備函數(shù)(?beforeEach?)。

fakeAsync

在一個(gè)特殊的fakeAsync 測(cè)試區(qū)域中運(yùn)行測(cè)試(?it?)的函數(shù)體,以便啟用線性風(fēng)格的控制流。

tick

通過在 fakeAsync 測(cè)試區(qū)域中刷新定時(shí)器和微任務(wù)(micro-task)隊(duì)列來仿真時(shí)間的流逝以及異步活動(dòng)的完成。

好奇和執(zhí)著的讀者可能會(huì)喜歡這篇長(zhǎng)博客:
Tasks, microtasks, queues and schedules

接受一個(gè)可選參數(shù),它可以把虛擬時(shí)鐘往前推進(jìn)特定的微秒數(shù)。清除調(diào)度到那個(gè)時(shí)間幀中的異步活動(dòng)。

inject

從當(dāng)前的 TestBed 注入器中把一個(gè)或多個(gè)服務(wù)注入到一個(gè)測(cè)試函數(shù)中。它不能用于注入組件自身提供的服務(wù)。

discardPeriodicTasks 當(dāng) ?fakeAsync ?測(cè)試程序以正在運(yùn)行的計(jì)時(shí)器事件任務(wù)(排隊(duì)中的 ?setTimeOut ?和 ?setInterval ?的回調(diào))結(jié)束時(shí),測(cè)試會(huì)失敗,并顯示一條明確的錯(cuò)誤信息。
一般來講,測(cè)試程序應(yīng)該以無排隊(duì)任務(wù)結(jié)束。當(dāng)待執(zhí)行計(jì)時(shí)器任務(wù)存在時(shí),調(diào)用 ?discardPeriodicTasks ?來觸發(fā)任務(wù)隊(duì)列,防止該錯(cuò)誤發(fā)生。
flushMicrotasks

當(dāng) ?fakeAsync ?測(cè)試程序以待執(zhí)行微任務(wù)(比如未解析的承諾)結(jié)束時(shí),測(cè)試會(huì)失敗并顯示明確的錯(cuò)誤信息。

一般來說,測(cè)試應(yīng)該等待微任務(wù)結(jié)束。當(dāng)待執(zhí)行微任務(wù)存在時(shí),調(diào)用 ?flushMicrotasks ?來觸發(fā)微任務(wù)隊(duì)列,防止該錯(cuò)誤發(fā)生。

ComponentFixtureAutoDetect

一個(gè)服務(wù)提供者令牌,用于開啟自動(dòng)變更檢測(cè)。

getTestBed 獲取當(dāng)前 ?TestBed ?實(shí)例。通常用不上,因?yàn)??TestBed ?的靜態(tài)類方法已經(jīng)夠用。?TestBed ?實(shí)例有一些很少需要用到的方法,它們沒有對(duì)應(yīng)的靜態(tài)方法。

TestBed 類摘要

?TestBed ?類是 Angular 測(cè)試工具的主要類之一。它的 API 很龐大,可能有點(diǎn)過于復(fù)雜,直到你一點(diǎn)一點(diǎn)的探索它們。

傳給 ?configureTestingModule ?的模塊定義是 ?@NgModule? 元數(shù)據(jù)屬性的子集。

type TestModuleMetadata = {
  providers?: any[];
  declarations?: any[];
  imports?: any[];
  schemas?: Array<SchemaMetadata | any[]>;
};

每一個(gè)重載方法接受一個(gè) ?MetadataOverride<T>?,這里 ?T? 是適合這個(gè)方法的元數(shù)據(jù)類型,也就是 ?@NgModule?、?@Component?、?@Directive? 或者 ?@Pipe? 的參數(shù)。

type MetadataOverride<T> = {
  add?: Partial<T>;
  remove?: Partial<T>;
  set?: Partial<T>;
};

?TestBed ?的 API 包含了一系列靜態(tài)類方法,它們更新或者引用全局的 ?TestBed ?實(shí)例。

在內(nèi)部,所有靜態(tài)方法在 ?getTestBed()? 函數(shù)返回的當(dāng)前運(yùn)行時(shí)間的 ?TestBed ?實(shí)例上都有對(duì)應(yīng)的方法。

在 ?BeforeEach()? 內(nèi)調(diào)用 ?TestBed ?方法,以確保在運(yùn)行每個(gè)單獨(dú)測(cè)試時(shí),都有嶄新的開始。

這里列出了最重要的靜態(tài)方法,以使用頻率排序。

方法

詳情

configureTestingModule

測(cè)試墊片(karma-test-shimbrowser-test-shim)創(chuàng)建了初始測(cè)試環(huán)境和默認(rèn)測(cè)試模塊。默認(rèn)測(cè)試模塊是使用基本聲明和一些 Angular 服務(wù)替代品,它們是所有測(cè)試程序都需要的。
調(diào)用 configureTestingModule 來為一套特定的測(cè)試定義測(cè)試模塊配置,添加和刪除導(dǎo)入、(組件、指令和管道的)聲明和服務(wù)提供者。

compileComponents

在配置好測(cè)試模塊之后,異步編譯它。如果測(cè)試模塊中的任何一個(gè)組件具有 templateUrl 或 styleUrls,那么你必須調(diào)用這個(gè)方法,因?yàn)楂@取組件的模板或樣式文件必須是異步的。
調(diào)用完 compileComponents 之后,TestBed 的配置就會(huì)在當(dāng)前測(cè)試期間被凍結(jié)。

createComponent<T>

基于當(dāng)前 TestBed 的配置創(chuàng)建一個(gè)類型為 T 的組件實(shí)例。調(diào)用 createComponent 之后,TestBed 的配置就會(huì)在當(dāng)前測(cè)試期間被凍結(jié)。

overrideModule

替換指定的 NgModule 的元數(shù)據(jù)?;叵胍幌?,模塊可以導(dǎo)入其它模塊。overrideModule 方法可以深入到當(dāng)前測(cè)試模塊深處,修改其中一個(gè)內(nèi)部模塊。

overrideComponent

替換指定組件類的元數(shù)據(jù),該組件類可能嵌套在一個(gè)很深的內(nèi)部模塊中。

overrideDirective

替換指定指令類的元數(shù)據(jù),該指令可能嵌套在一個(gè)很深的內(nèi)部模塊中。

overridePipe

替換指定管道類的元數(shù)據(jù),該管道可能嵌套在一個(gè)很深的內(nèi)部模塊中。

inject

從當(dāng)前 TestBed 注入器獲取一個(gè)服務(wù)。inject 函數(shù)通常都能勝任這項(xiàng)工作,但是如果它沒法提供該服務(wù)時(shí)就會(huì)拋出一個(gè)異常。
如果該服務(wù)是可選的呢?
TestBed.inject() 方法可以接受可選的第二參數(shù),當(dāng) Angular 找不到指定的服務(wù)提供者時(shí),就會(huì)返回該對(duì)象(下面這個(gè)例子中是 null):

expect(TestBed.inject(NotProvided, null)).toBeNull();
調(diào)用了 TestBed.inject 之后然后通過調(diào)用,TestBed 的配置就會(huì)在當(dāng)前測(cè)試期間被凍結(jié)。
initTestEnvironment

為整套測(cè)試的運(yùn)行初始化測(cè)試環(huán)境。
測(cè)試墊片(karma-test-shimbrowser-test-shim)會(huì)為你調(diào)用它,所以你很少需要自己調(diào)用它。
這個(gè)方法只能被調(diào)用一次。如果確實(shí)需要在測(cè)試程序運(yùn)行期間改變這個(gè)默認(rèn)設(shè)置,那么先調(diào)用 resetTestEnvironment。
指定 Angular 編譯器工廠,PlatformRef,和默認(rèn) Angular 測(cè)試模塊。以 @angular/platform-<platform_name>/testing/<platform_name> 的形式提供非瀏覽器平臺(tái)的替代品。

resetTestEnvironment

重設(shè)初始測(cè)試環(huán)境,包括默認(rèn)測(cè)試模塊在內(nèi)。

少數(shù) ?TestBed ?實(shí)例方法沒有對(duì)應(yīng)的靜態(tài)方法。它們很少被使用。

ComponentFixture 類

?TestBed.createComponent<T>? 會(huì)創(chuàng)建一個(gè)組件 ?T? 的實(shí)例,并為該組件返回一個(gè)強(qiáng)類型的 ?ComponentFixture?。

?ComponentFixture ?的屬性和方法提供了對(duì)組件、它的 DOM 和它的 Angular 環(huán)境方面的訪問。

ComponentFixture 的屬性

下面是對(duì)測(cè)試最重要的屬性,以使用頻率排序。

屬性

詳情

componentInstance

被 TestBed.createComponent 創(chuàng)建的組件類實(shí)例。

debugElement

與組件根元素關(guān)聯(lián)的 DebugElement。
debugElement 提供了在測(cè)試和調(diào)試期間深入探查組件及其 DOM 元素的功能。它對(duì)于測(cè)試者是一個(gè)極其重要的屬性。

nativeElement

組件的原生根 DOM 元素。

changeDetectorRef

組件的 ChangeDetectorRef。
在測(cè)試一個(gè)擁有 ChangeDetectionStrategy.OnPush 的組件,或者在組件的變化測(cè)試在你的程序控制下時(shí),ChangeDetectorRef 是最重要的。

ComponentFixture 方法

fixture 方法使 Angular 對(duì)組件樹執(zhí)行某些任務(wù)。在觸發(fā) Angular 行為來模擬的用戶行為時(shí),調(diào)用這些方法。

下面是對(duì)測(cè)試最有用的方法。

方法

詳情

detectChanges

為組件觸發(fā)一輪變化檢查。
調(diào)用它來初始化組件(它調(diào)用 ngOnInit)?;蛘咴谀愕臏y(cè)試代碼改變了組件的數(shù)據(jù)綁定屬性值后調(diào)用它。Angular 不能檢測(cè)到你已經(jīng)改變了 personComponent.name 屬性,也不會(huì)更新 name 的綁定,直到你調(diào)用了 detectChanges。
之后,運(yùn)行 checkNoChanges,來確認(rèn)沒有循環(huán)更新,除非它被這樣調(diào)用:detectChanges(false)。

autoDetectChanges

如果你希望這個(gè)夾具自動(dòng)檢測(cè)變更,就把這個(gè)設(shè)置為 true。
當(dāng)自動(dòng)檢測(cè)打開時(shí),測(cè)試 fixture 監(jiān)聽 zone 事件,并調(diào)用 detectChanges。當(dāng)你的測(cè)試代碼直接修改了組件屬性值時(shí),你還是要調(diào)用 fixture.detectChanges 來觸發(fā)數(shù)據(jù)綁定更新。
默認(rèn)值是 false,喜歡對(duì)測(cè)試行為進(jìn)行精細(xì)控制的測(cè)試者一般保持它為 false。

checkNoChanges

運(yùn)行一次變更檢測(cè)來確認(rèn)沒有待處理的變化。如果有未處理的變化,它將拋出一個(gè)錯(cuò)誤。

isStable

如果 fixture 當(dāng)前是穩(wěn)定的,則返回 true。如果有異步任務(wù)沒有完成,則返回 false

whenStable

返回一個(gè)承諾,在 fixture 穩(wěn)定時(shí)解析。
要想在完成了異步活動(dòng)或異步變更檢測(cè)之后再繼續(xù)測(cè)試,可以對(duì)那個(gè)承諾對(duì)象進(jìn)行掛鉤。

destroy

觸發(fā)組件的銷毀。

DebugElement

?DebugElement ?提供了對(duì)組件的 DOM 的訪問。

?fixture.debugElement? 返回測(cè)試根組件的 ?DebugElement?,通過它你可以訪問(查詢)fixture 的整個(gè)元素和組件子樹。

下面是 ?DebugElement ?最有用的成員,以使用頻率排序。

成員

詳情

nativeElement

與瀏覽器中 DOM 元素對(duì)應(yīng)(WebWorkers 時(shí),值為 null)。

query

調(diào)用 query(predicate: Predicate<DebugElement>) 會(huì)在子樹的任意深度中查找并返回能和謂詞函數(shù)匹配的第一個(gè) DebugElement。

queryAll

調(diào)用 queryAll(predicate: Predicate<DebugElement>) 會(huì)在子樹的任意深度中查找能和謂詞函數(shù)匹配的所有 DebugElement

injector

宿主依賴注入器。比如,根元素的組件實(shí)例注入器。

componentInstance

元素自己的組件實(shí)例(如果有)。

context

為元素提供父級(jí)上下文的對(duì)象。通常是控制該元素的祖級(jí)組件實(shí)例。
當(dāng)一個(gè)元素被 *ngFor 重復(fù),它的上下文為 NgForOf,它的 $implicit 屬性值是該行的實(shí)例值。比如,*ngFor="let hero of heroes" 里的 hero

children

DebugElement 的直接子元素。可以通過繼續(xù)深入 children 來遍歷這棵樹。

?DebugElement ?還有 ?childNodes?,即 ?DebugNode ?對(duì)象列表。?DebugElement ?從 ?DebugNode ?對(duì)象衍生,而且通常節(jié)點(diǎn)(node)比元素多。測(cè)試者通常忽略普通節(jié)點(diǎn)。

parent

DebugElement 的父級(jí)。如果 DebugElement 是根元素,parent 為 null。

name

元素的標(biāo)簽名字,如果它是一個(gè)元素的話。

triggerEventHandler

如果在該元素的 listeners 集合中有相應(yīng)的監(jiān)聽器,就根據(jù)名字觸發(fā)這個(gè)事件。第二個(gè)參數(shù)是該處理器函數(shù)所需的事件對(duì)象
如果事件缺乏監(jiān)聽器,或者有其它問題,考慮調(diào)用 nativeElement.dispatchEvent(eventObject)。

listeners

元素的 @Output 屬性以及/或者元素的事件屬性所附帶的回調(diào)函數(shù)。

providerTokens

組件注入器的查詢令牌。包括組件自己的令牌和組件的 providers 元數(shù)據(jù)中列出來的令牌。

source

source 是在源組件模板中查詢這個(gè)元素的處所。

references

與模板本地變量(比如 #foo)關(guān)聯(lián)的詞典對(duì)象,關(guān)鍵字與本地變量名字配對(duì)。

?DebugElement.query(predicate)? 和 ?DebugElement.queryAll(predicate)? 方法接受一個(gè)條件方法,它過濾源元素的子樹,返回匹配的 ?DebugElement?。

這個(gè)條件方法是任何接受一個(gè) ?DebugElement ?并返回真值的方法。下面的例子查詢所有擁有名為 ?content ?的模塊本地變量的所有 ?DebugElement?:

// Filter for DebugElements with a #content reference
const contentRefs = el.queryAll( de => de.references['content']);

Angular 的 ?By ?類為常用條件方法提供了三個(gè)靜態(tài)方法:

靜態(tài)方法

詳情

By.all

返回所有元素

By.css(selector)

返回符合 CSS 選擇器的元素

By.directive(directive)

返回 Angular 能匹配一個(gè)指令類實(shí)例的所有元素

// Can find DebugElement either by css selector or by directive
const h2 = fixture.debugElement.query(By.css('h2'));
const directive = fixture.debugElement.query(By.directive(HighlightDirective));


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)