Angular8 中引入 Jest 單元測試

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 模塊(不移除的話由於 e2e protractor 還要使用 jasmine 所以需要去解決衝突, 帥帥我不需要這玩意就直接刪除了, 保持環境乾淨, 並且公司產品也是好幾個版本都沒寫 e2e 因此帥帥我果斷移除掉, 需要的朋友自行百度解決 jestjasmine 的引用衝突即可.)

  • 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.jsoncompilerOptions/types : 將 jasmine 替換爲 jest

file

  • 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/*
    • --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 總帶有 karmajasmine 的依賴

3.2 移除 e2e 和 protractor

  • protractor.conf.js
  • app.e2e.spec.ts
  • tsconfig.e2e.json

4. 運行測試

npm run test

file

此時,在命令行中運行測試命令,就應該能夠順利把測試跑起來並通過了。如果沒有通過,可能是因爲我們在 src/tsconfig.spec.json 中的 file 配置中有 test.js 的配置,這是 Karma 的 setup 文件,刪掉這行配置並刪除對應的文件,(src/tsconfig.app.json 中出現的 test.js 也可一併刪除),重新跑一遍測試命令.

在這裏插入圖片描述

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章