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 也可一并删除),重新跑一遍测试命令.

在这里插入图片描述

在这里插入图片描述

发布了25 篇原创文章 · 获赞 36 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/DreamLi1314/article/details/105641750