前言
前一篇大致理解了如何測試一個單純的元件或是帶有繫結的元件。但在實務的應用上,元件經常依賴著其他服務元件,因此這個例子要實作的範例是 - 如何測試一個帶有依賴的元件?
- 在這個範例中,一個帶有依賴的元件可以拆成
- 製作一個 welcome 元件 + 一個負責提供資料的 user 服務元件
環境建立
輸入 ng g c welcome -m app
在產生 welcome 元件後將其註冊到 app.module 內。
輸入 ng g s user
產生 user 服務元件
到 app.module 註冊 user 服務元件
1 | import { BrowserModule } from '@angular/platform-browser'; |
基本的檔案建立完成後,接著就是撰寫程式碼了。
user.service
1 | import { Injectable } from '@angular/core'; |
在服務元件內建立 isLoggedIn
屬性以及 user
物件,這是待會要提供給 welcomeComponent 的內容。
welcome Template
1 | <h3 class="welcome"><i>{{welcome}}</i></h3> |
welcome class
1 | import { Component, OnInit } from '@angular/core'; |
最後把 app-welcome 標籤加到 app.component.html 。
1 | <app-welcome></app-welcome> |
運行開發伺服器,看看執行結果。
測試帶有依賴的元件
在這個範例裡 WelcomeComponent 依賴著 user 服務元件的資料,接收到資料後根據 isLoggedIn
的狀態決定顯示的語句。
welcome.component.spec
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; |
這裡跟之前練習有依賴關係的服務元件的測試時有點像,我們在 TestBed.configureTestingModule 內宣告了:
- 待測試的元件 - WelcomeComponent
- 在 providers 陣列中添加了 UserService 服務元件
- 並且透過 useValue 將 UserService 的資料換成測試用的資料
被測試的元件不一定要注入真正的服務,可以是個模擬或偽造出來的資料。
這裡的主要目的是測試元件,而不是服務。
有些時候,服務元件可能連自身都有問題,不應該讓它干擾對元件的測試。
注入真實的 UserService 有可能很麻煩,像是:
- 真實的服務可能詢問使用者登入憑據
- 也可能試圖連線認證伺服器
這樣會很難處理這些行為,所以建立和註冊 UserService 替身 (userServiceStub) ,會讓測試更加容易。
獲得注入的服務
我們製作了一個 UserService 的替身 - userServiceStub
,那麼該如何取用它呢?
Angular 的注入系統是層次化的。
可以有很多層注入器,從根 TestBed 建立的注入器下來貫穿整個元件樹。
因此這邊有兩種做法:
第一種做法 - 最安全並有效的獲取注入服務的方法:
- 從被測元件的注入器獲取
- 元件注入器是 fixture 的 DebugElement 的屬性之一。
1 | // UserService actually injected into the component |
第二種做法 - 透過 TestBed.get() 來使用根注入器獲取該服務:
1 | // UserService from the root injector |
不過這只有當 Angular 元件需要的恰好是該測試的根注入器時才能正常使用。
而加入這部分後,我們的程式碼目前是這個樣子的:
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; |
加入一些測試例
接著補上一些測試例:
1 | it('should welcome the user', () => { |
- 第一個測試檢查
el.textContent
有沒有包含「歡迎」、「Test User」 - 第二個測試檢查當變更姓名時,顯示是否仍包含「Bubba」
- 第三個測試檢查當未授權登入時,顯示是否不包含「歡迎」
- 且顯示文字「未授權, 請登入!」