Angular8 中引入 Jest 單元測試
文章目錄
Angular 項目默認的單元測試框架是 Karma + jasmine, 帥帥我的項目 AngBoot: https://github.com/DreamLi1314/angboot 部署到 CI 上之後發現跑 Karma 測試用例時需要啓動瀏覽器, 雖然可以配置解決, 但是在自己部署到雲服務上時
./gradlew clean build
每次都要在 angular 的 test 階段失敗(沒有瀏覽器—雖然也可以跳過test), 因此感覺特別不爽, 於是乎, 就提了一個 Feature----Feature #15:https://github.com/DreamLi1314/angboot/issues/15, 也就有了這篇文章,
好了, 一起瞅瞅吧!
1. Jest 和 Karma 的區別
1.1 Karma 存在的問題
- Karma 需要先把 Angular 應用整體編譯之後再在瀏覽器中跑測試,跑測試的時間比較長;
- Karma 測試結果不穩定(很可能是因爲異步操作引起的),單個文件和整體測試時的測試結果不一致;
- 報錯信息模糊不清,無法定位問題。特別是在有大量測試需要修復的情況下,難以定位問題的根本原因。
1.2 Jest 的優勢
- 不需要整體編譯,可以單文件測試
- 測試結果穩定
- 報錯清楚,易於定位問題
- 開箱即用,基本算是全家桶,包含了測試需要的大部分工具:測試結構、斷言、spies、mocks
- 直接提供了測試覆蓋率報告
- 快照測試
- 非常強大的模塊級 mock 功能
- watch 模式僅僅測試和被修改文件相關的測試,速度非常快
所以還等什麼, 趕快跟着帥帥一起遷移到 Jest 吧…
2. 遷移到 Jest
2.1 安裝 Jest
npm install --save-dev jest jest-canvas-mock jest-junit @types/jest @angular-builders/jest
npm install jest-codemods
jest
---- Jest 測試框架jest-junit
---- jest junit 測試jest-canvas-mock
---- 配置好的 mock 數據@types/jest
---- Jest 的 typings@angular-builders/jest
— jest 構建器jest-codemods
---- 代碼插件
2.2 配置 Jest
- a. angular.json 中 修改
test
構建器:
"test": {
"builder": "@angular-builders/jest:run",
"options": {
"reporters": [
"default",
"jest-junit"
]
}
},
同時移除
e2e
模塊(不移除的話由於 e2eprotractor
還要使用 jasmine 所以需要去解決衝突, 帥帥我不需要這玩意就直接刪除了, 保持環境乾淨, 並且公司產品也是好幾個版本都沒寫 e2e 因此帥帥我果斷移除掉, 需要的朋友自行百度解決jest
和jasmine
的引用衝突即可.)
- b. 在項目根路徑下添加
jest.config.js
配置文件:
module.exports = {
globals: {
'ts-jest': {
tsConfigFile: './tsconfig.spec.json',
},
},
setupFiles: ["jest-canvas-mock", "<rootDir>/src/setupJest.ts"]
};
- c. 創建自己的 setup 文件以及全局的 mock 文件:
// setupJest.ts
import "./jestGlobalMocks.ts"; // jest 全局的 mock
// jestGlobalMocks.ts
const mock = () => {
let storage = {};
return {
getItem: key => key in storage ? storage[key] : null,
setItem: (key, value) => storage[key] = value || "",
removeItem: key => delete storage[key],
clear: () => storage = {},
};
};
Object.defineProperty(window, "localStorage", {value: mock()});
Object.defineProperty(window, "sessionStorage", {value: mock()});
Object.defineProperty(window, "getComputedStyle", {
value: () => ["-webkit-appearance"]
});
jsdom 並沒有實現所有的 window 上的對象和方法,所以有時我們需要自己給 window 打個補丁。
在這裏 mock localStorage 是可選的,如果我們在代碼中並沒有使用。但是 mock getComputedStyle 是必須的,因爲 Angular 會檢查它在哪個瀏覽器中執行。如果沒有 mock getComputedStyle,我們的測試代碼將無法執行。
- c. 修改
tsconfig.spec.json
的compilerOptions/types
: 將jasmine
替換爲jest
- d. 在 package.json 中添加執行 test 的script
"test": "JEST_JUNIT_OUTPUT=./build/test-results/junit.xml npm run ng -- test angboot-web --ci --runInBand --reporters=default --reporters=jest-junit",
"test:watch": "JEST_JUNIT_OUTPUT=./build/test-results/junit.xml npm run ng -- test angboot-web --ci --runInBand --reporters=default --reporters=jest-junit --watch"
-
- angboot-web 是項目名, 參看
angular.json/projects/*
- angboot-web 是項目名, 參看
-
--ci --runInBand
CI服務器通常在單核上運行您的代碼,因此並行化可能會降低測試速度。如果遇到這種情況,請使用--runInBand
標誌明確告訴Jest您要一對一地運行測試(就像Karma或Mocha一樣)
3. 移除 Karma
3.1 移除 Karma 的依賴包
npm uninstall karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter @types/jasmine @types/jasminewd2 jasmine-core jasmine-spec-reporter
簡單點就刪掉
package.json
總帶有karma
和jasmine
的依賴
3.2 移除 e2e 和 protractor
- protractor.conf.js
- app.e2e.spec.ts
- tsconfig.e2e.json
- …
4. 運行測試
npm run test
此時,在命令行中運行測試命令,就應該能夠順利把測試跑起來並通過了。如果沒有通過,可能是因爲我們在 src/tsconfig.spec.json 中的 file 配置中有 test.js 的配置,這是 Karma 的 setup 文件,刪掉這行配置並刪除對應的文件,(src/tsconfig.app.json 中出現的 test.js 也可一併刪除),重新跑一遍測試命令.