使用Karma為Angular組件撰寫單元測試案例
我想為你的Angular網頁應用程序編寫單元測試。加速生產時間並不能成為積累技術債的合理理由。以下是一些開始的有力理由:
-
單元測試幫助盡可能早地識別問題,尤其是當多個團隊在同一個代碼庫上工作,不經意地引入了錯誤。避免在深夜接到生產支持的電話是一個值得追求的目標。
-
測試使您能夠自信地重構代碼,確保您的應用程序繼續按預期運行。您可以將您的代碼分割為可管理的,可測試的單元,而不是處理一個龐大的系統。
-
您公司的政策可能要求某種程度的代碼覆蓋率,通常為80%或更高。
如果你是新手,你可能不知道如何開始,或者為什麼這個重要。幸運的是,Angular讓它變得很容易。開始,只需在您的項目目錄中運行以下命令:
npm run test
這將在本地主機的9876端口打開一個Chrome瀏覽器窗口。
點擊”Debug”按鈕以啟動測試。
此時,由於我們還沒有寫任何測試,所以不會有任何測試運行。但是,您可以開始撰寫測試用例以覆蓋特定的,獨立的代碼片段。例如,讓我們考慮一個login.component.ts
檔案,其中包含一個login()
方法,該方法將一個布爾標誌從假轉為真:
export class LoginComponent {
isLogon = false
login() {
this.isLogon = true
}
}
接下來,創建一個名為login.component.spec.ts
的檔案以撰寫您的測試用例。如下所示撰寫您的第一個測試用例:
import { async, ComponentFixture, TestBed } from "@angular/core/testing"
import { LoginComponent } from "./login.component"
describe("LoginComponent", () => {
let component: LoginComponent
let fixture: ComponentFixture<LoginComponent>
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LoginComponent],
}).compileComponents()
}))
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it("should be able to log on", () => {
component.login()
expect(component.isLogon).toBeTruthy()
})
})
在您的describe()
函式中,您將找到測試用例。每個案例都在其自己的it()
函式中。這裡的目標是測試isLogon
標誌在觸發login()
方法後是否變為真。
您的第一個測試用例應該通過!如果另一個開發者修改了您的代碼,您的測試將捕獲它:
在現實世界的情境中,您可能會向服務器發送API呼叫。但是,在您的測試期間重要的是不要真的撥打API。您應該用stub數據模擬您的API呼叫。
例如,讓我們加強我們的LoginComponent
以進行服務呼叫:
import { AuthenticationService } from "../../services/authentication.service"
export class LoginComponent {
constructor(private authenticationService: AuthenticationService) {}
isLogon = false
login() {
this.authenticationService.login().subscribe(
data => {
this.isLogon = true
},
error => {
this.isLogon = false
}
)
}
}
現在,您的測試將會失敗,因為AuthenticationService尚未注入我們的測試環境。我們可以如下所示修復這個問題:
import { async, ComponentFixture, TestBed } from "@angular/core/testing"
import { LoginComponent } from "./login.component"
import { AuthenticationService } from "../../services/authentication.service"
import { of } from "rxjs"
const stubData = {
username: "testing",
}
class FakeAuthenticationService {
login() {
return of(stubData)
}
}
describe("LoginComponent", () => {
let component: LoginComponent
let fixture: ComponentFixture<LoginComponent>
const newFakeAuthenticationService = new FakeAuthenticationService()
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LoginComponent],
providers: [
{
provide: AuthenticationService,
useValue: newFakeAuthenticationService,
},
],
}).compileComponents()
}))
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it("should be able to log on", () => {
component.login()
expect(component.isLogon).toBeTruthy()
})
})
您的測試用例現在應該通過!
這個例子為了演示的目的而簡化,但是重要的要取的是,你不應該避免撰寫單元測試。