文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Jest 写前端单元测试入门

2024-12-02 20:15

关注

本文转载自微信公众号「前端GoGoGo」,作者Joel  。转载本文请联系前端GoGoGo公众号。

写测试能减少 bug,提高代码质量。同时,重构测试覆盖率高的代码,不担心改坏以前的功能。

前端的测试可以分为 3 类:单元测试,集成测试 和 UI 测试。

本文主要介绍用 Jest[1] 来写单元测试。Jest 是一款优雅、简洁的 JavaScript 测试框架。下面的是用 Jest 写的单元测试:

import sum from './sum';  test('sum', () => {   expect(sum(1, 2)).toBe(3);   expect(sum(-1, -2)).toBe(-3); }); 

sum 是要测试的函数。test(...) 是包裹了要测试的一个特性。expect(...) 是断言:期望 sum(1, 2) 的值是 3,如果 sum(1, 2) 的值不是 3,则该测试会失败。

Jest 主要包含 3 块内容:

1 安装

Jest 是依赖 Node.js[2] 的。安装好 Node 后,初始化 node 项目:

npm init -y 

安装 Jest

npm install --save-dev jest 

支持 Babel

需要支持 ES6, ES7 等语法,则安装 Babel 相关依赖:

yarn add --dev babel-jest @babel/core @babel/preset-env 

在项目根目录下创建 Babel 配置文件:babel.config.js 来配置与当前 Node 版本兼容的 Babel:

module.exports = {   presets: [['@babel/preset-env', {targets: {node: 'current'}}]], }; 

支持 TypeScript

yarn add --dev @babel/preset-typescript 

在项目根目录下创建 TypeScript 配置文件:tsconfig.json 。内容类似:

{   "compilerOptions": {       "module": "commonjs",       "noImplicitAny": true,       "removeComments": true,       "preserveConstEnums": true,       "sourceMap": true,       "esModuleInterop": true   },   "include": [     "src*"   ],   "exclude": [     "node_modules"   ] } 

2 运行

运行项目里的所有测试用例

需要在 package.json 中加如下内容:

{   "scripts": {     "test": "jest"   } } 

测试用例要写在单独的文件,而不是放在要测试的文件里。测试用例的文件名需要带 .spec.[js|ts] 或 .test.[js|ts]。比如,一个文件叫 sum.js,对其进行测试,一般在该文件的相同目录下,创建个测试用例文件 sum.spec.js。

执行 npm run test 即可运行项目中,就会运行所有的测试用例。

运行特定的一个测试用例文件

在项目根目录行执行 yarn jest 测试用例文件路径 或 npm run test 测试用例文件路径。

运行特定的一个测试用例

只需将要运行用例的 test(...) 改成 test.only(...),然后再运行该测试用例文件。类似的,运行一组用例,把 describe(...) 改成 describe.only(...)。

获取测试覆盖率

测试覆盖率(test coverage) 衡量的是功能代码被测试用例覆盖的比率。对代码质量要求高的项目,会要求测试覆盖率在 90% 以上。

获取测试覆盖率的命令:

jest --coverage 

3 Jest API

断言 API

编写测试时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设。比如:

expect(2 + 2).toBe(4) 

Jest 支持主要断言API如下:

所有的断言API见:这里[3]。

Jest 场景

测试异步代码

处理异步一般有 3 种方式:回调, Promise 和 Async/Await。

回调

业务代码:

function fetchNameCallback(cb: (name: string) => void) {     setTimeout(() => {       cb('Joel');     }, 1000) } 

用例代码如下:

test('async: callback', done => {   fetchNameCallback(name => {     expect(name).toBe('Joel');     done(); // 通知 Jest,回调结束了   }); }); 

注意:异步回调结束后,需要调用参数 done。以此来通知 Jest,回调结束了。

Promise

业务代码:

function fetchName(throwError?: boolean) {   return new Promise((resolve, reject) => {     setTimeout(() => {       if(!throwError) {         resolve('Joel')       } else {         reject('error happened')       }     }, 1000)   }); } 

用例代码如下:

test('async: Promise', () => {   fetchName().then(name => {     expect(name).toBe('Joel');   });   //  异常处理   fetchName(true).catch(e => {     expect(e).toMatch('error');   }); }); 

Async/Await

业务代码和上面的 Promise 的相同。

用例代码如下:

test.only('Async/Await', async () => {   const name = await fetchName();   expect(name).toBe('Joel');   // 异常处理   try {     fetchName(true);   } catch(e) {     expect(e).toMatch('error');   } }); 

测试前的准备操作和测试后的整理操作

写测试的时候可能需要在测试前做一些准备工作。运行测试后,需要做进行一些整理工作。用 Jest 这么写:

每次用例的前后都执行

// 前 beforeEach(() => { });  // 后 afterEach(() => { }); 

所有用例的前后执行

beforeAll(() => { });  afterAll(() => { }); 

只会被执行一次。

Mock 外部依赖

我们在测试模块功能时,如果模块对外部的依赖的是有问题的,也会导致测试的不通过。为规避这种问题,会 Mock外部依赖:用一个不出错的实现来代替外部依赖。

Mock 第三方包的部分 api

这边以 Mock axios[4] 为例,业务代码:

axiosFetchUser = () => {   return axios.get('/user'); } 

测试代码:

test('fetch user', () => {   axios.get.mockImplementation(url => {     if(/^\/user$/.test(url)) {       return Promise.resolve({name: 'Joel'})     }     return Promise.resolve('other')   })    axiosFetchUser().then(({ name }) => {     expect(name).toBe('Joel');   }) }); 

其中 axios.get.mockImplementation(...) Mock了 axios.get 的实现。

Mock 某个文件的部分内容

我们有个工具函数文件 utils.ts,内容如下:

const guid = () => ...; export default guid;  export const getYear = () => ...; export const getMonth = () => ...; 

我们只 Mock 上面文件中的 guid 和 getYear,其他部分保持原状。这么写:

jest.mock('./util', () => {   const originalModule = jest.requireActual('./util');   return {     __esModule: true,     ...originalModule,     default: () => 'abc', // mock guid     getYear: () => 2021,   }; }); 

Mock 完整的第三方包和文件

Mock 完整的第三方包和文件只需做 2 步。

在 __mocks__/ 下建 Mock 的文件。

通知 Jest 用 Mock 的实现:jest.mock('./moduleName') 或 jest.mock('module_name')。

详细介绍见: 这里[5]。

最后

行动起来,开始练习写单元测试吧~

参考资料

[1]Jest: https://jestjs.io/

[2]Node.js: https://nodejs.org/en/

[3]这里: https://jestjs.io/zh-Hans/docs/expect

[4]axios: https://axios-http.com/

[5]这里: https://jestjs.io/zh-Hans/docs/manual-mocks


来源:前端GoGoGo内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯